Select between two dynamic (variable) dates SQL - sql

I have a query that runs once a day that I would like to share however I need to remove the part where the other users in my team will have to edit it. Essentially, it's run Monday thru Friday. I want, if today is Monday, give me the last 3 days worth of data. Any other day, just give me yesterday's data.
So far this is what I have:
Update: They are all strings, so now I get the following error.
"Incorrect syntax near the keyword 'BETWEEN'."
DECLARE #daychecker varchar(max) = FORMAT(GETDATE(), 'dddd')
DECLARE #daterange0 varchar(max)
DECLARE #daterange1 varchar(max) = FORMAT(GETDATE()-3, 'yyyy-MM-dd')
DECLARE #daterange2 varchar(max) = FORMAT(GETDATE()-1, 'yyyy-MM-dd')
IF #daychecker = 'Wednesday'
BEGIN
SET #daterange0 = BETWEEN #daterange1 AND #daterange2
END
ELSE
BEGIN
SET #daterange0 = FORMAT(GETDATE()-1, 'yyyy-MM-dd')
END
SELECT #daterange0;
The result for today as an example should return yesterday's date. But that doesn't work. I will consider all options including hardcoding some sort of master start date that we can count from like maybe the start of the year or something.

You're much better off defining 2 dates, a start date and end date, and filtering your query based on them. EDIT: I'm now unsure if you want actual dates for filtering data, or a label for a report. I modified my answer to include the latter, use whichever you want and ignore the other ...
DECLARE #DateStart DATE
DECLARE #DateEnd DATE
DECLARE #LableRange varchar(max)
SELECT DATEPART(WEEKDAY, GETDATE()) --Sun=1, Mon=2, ...
IF DATEPART(WEEKDAY, GETDATE()) = 2 BEGIN
SET #DateStart = DATEADD (DAY, -5,GETDATE())
SET #DateEnd = DATEADD (DAY, -2,GETDATE())
SET #LableRange = CONCAT(FORMAT(#DateStart, 'yyyy-MM-dd'), ', '
, FORMAT(DATEADD(day,1,#DateStart), 'yyyy-MM-dd'), ', '
, FORMAT(DATEADD(day,2,#DateStart), 'yyyy-MM-dd'))
-- or maybe this format is better
--SET #LableRange = CONCAT('BETWEEN '
--, FORMAT(#DateStart, 'yyyy-MM-dd'), ' AND '
--, FORMAT(DATEADD(day,2,#DateStart), 'yyyy-MM-dd'))
END ELSE BEGIN
SET #DateStart = DATEADD (DAY, -1,GETDATE())
SET #DateEnd = GETDATE()
SET #LableRange = FORMAT(#DateStart, 'yyyy-MM-dd')
END
SELECT #LableRange
SELECT * FROM SomeTable as T
WHERE T.TestDate < #DateEnd AND T.TestDate >= #DateStart
Note that this works even if the date you are filtering on is a datetime instead of pure date.

Related

How to get dates between time range in sql server

I need to write a stored procedure in which i will get begin date and end date. for eg: start date is 05/07/2015 and end date is 28/08/2015. I need to write a query which will fetch details between 01/07/2015 and 31/08/2015. It should fetch details between 1st day of month selected for begin date and last day of month selected for end date.
This is what I tried, but it isn't working:
DATEDIFF(month,'2014-06-05','2014-08-05')
You can compare the dates using the common operators "<" and ">",
Example:
select * from table_name where '2014-06-05' < datefield and datefield < '2014-08-05'
DECLARE #StartDate DATETIME
DECLARE #EndDate DATETIME
SET #StartDate = convert(DATE, '20140705' ,112)
SET #EndDate = convert(DATE, '20140828' ,112)
SELECT * FROM [TableName] WHERE [TableName].DateField BETWEEN
dateadd(d,-(datepart(d, #StartDate)-1),#StartDate) AND
dateadd(d,-1,dateadd(m,1, dateadd(d,-(datepart(d, #EndDate)-1),#EndDate)))
It sounds like you need to find the first day of the month for '05/07/2015' and the last day of the month for '28/08/2015', then use those as the limits for your where clause.
This will easily convert a date to the first of the month:
declare #firstDate datetime = '2015-07-05'
declare #firstOfMonth datetime = dateadd(month,datediff(month,0,#firstDate),0)
select #firstDate
-- returns '2015-07-01 00:00:00.000'
To get to the last day of a month, use this:
declare #lastDate datetime = '2015-08-28'
declare #lastOfMonth datetime = dateadd(second,-1,dateadd(month,datediff(month,0,#lastDate)+1,0))
select #lastOfMonth
-- returns '2015-08-31 23:59:59.000'

Effective SQL Query to find a given month is in between two dates

I have two dates in my subscription table (start_date and end_date). I want to find out if the user is subscribed in the specified month or not? For ex: start_date=11/20/2011 and end_date=03/10/2012. I want to know all users who are subscribed in the month of Feb-2012 (02/2012).
Thank you.
Not sure if I understand, because other answers are "so" complicated, but as long as you only need to know if sbdy is subscribed within a month I would do this in a simple way:
SELECT
*
FROM
your_table
WHERE
CONVERT(datetime,'2012-02-01')
between DATEADD(month, DATEDIFF(month, 0, start_date), 0)
and DATEADD(month, DATEDIFF(month, 0, end_date), 0)
Just remember to put a first day of month within CONVERT function.
Something like this?
DECLARE #subscriptionStart datetime;
DECLARE #subscriptionEnd datetime;
DECLARE #monthStart datetime;
DECLARE #monthEnd datetime;
SET #subscriptionStart = '20111120';
SET #subscriptionEnd = '20120310';
SET #monthStart = '20120201';
SET #monthEnd = (dateadd(day,-1* day(dateadd(month,1,#monthStart)),dateadd(month,1,#monthStart)));
SELECT CASE
WHEN #subscriptionStart <= #monthStart
AND #subscriptionEnd >= #monthEnd
THEN 'month between dates'
ELSE 'month not between dates' END AS result
Given you pass in 201202 as the month of interest as a string.
Declare #StartOfMonth DateTime
Declare #EndOfMonth DateTime
Set #StartOfMonth = Convert(DateTime,#MyMonth + '01')
Set #EndOfMonth = DateSubtract(day, 1,DateAdd(month, 1, #StartOfMonth))
The it depends on whether you are interested in those subscribed for the whole month or any part of the month.
This will get you those for the whole month
Select * From Subscriptions Where
StartDate <= #StartOfMonth and EndDate >= #EndOfMonth
Or this will get you those for any part of the month
Select * From Subsciptions Where
(#StartOfMonth Between StartDate and EndDate)
Or
(#EndOfMonth Between StartDate and EndDate)
Well something like that anyway.
Try this
SET #SpecifiedDate = '2012/02/01'
SELECT * FROM myTable WHERE Start_Date >= #SpecifiedDate
OR
WHERE Month(#SpecifiedDate) = MONTH(Start_Date) AND YEAR(#SpecifiedDate) = YEAR(Start_Date)
You can use this
WHERE Month(#SpecifiedDate) >= MONTH(Start_Date) AND Month(#SpecifiedDate) <= MONTH(End_Date)
But I prefer using the the full date (with the year, month and 01 as day). Thus I won't worry about the year since SQL will handle the filtering
WHERE #SpecifiedDate >= Start_Date AND #SpecifiedDate <= End_Date

How to get Previous business day in a week with that of current Business Day using sql server

i have an ssis Package which runs on business days (mon-Fri). if i receive file on tuesday , background(DB), it takes previous business day date and does some transactions. If i run the job on friday, it has to fetch mondays date and process the transactions.
i have used the below query to get previous business date
Select Convert(varchar(50), Position_ID) as Position_ID,
TransAmount_Base,
Insert_Date as InsertDate
from tblsample
Where AsOfdate = Dateadd(dd, -1, Convert(datetime, Convert(varchar(10), '03/28/2012', 101), 120))
Order By Position_ID
if i execute this query i'll get the results of yesterdays Transactios. if i ran the same query on monday, it has to fetch the Fridays transactions instead of Sundays.
SELECT DATEADD(DAY, CASE DATENAME(WEEKDAY, GETDATE())
WHEN 'Sunday' THEN -2
WHEN 'Monday' THEN -3
ELSE -1 END, DATEDIFF(DAY, 0, GETDATE()))
I prefer to use DATENAME for things like this over DATEPART as it removes the need for Setting DATEFIRST And ensures that variations on time/date settings on local machines do not affect the results. Finally DATEDIFF(DAY, 0, GETDATE()) will remove the time part of GETDATE() removing the need to convert to varchar (much slower).
EDIT (almost 2 years on)
This answer was very early in my SO career and it annoys me everytime it gets upvoted because I no longer agree with the sentiment of using DATENAME.
A much more rubust solution would be:
SELECT DATEADD(DAY, CASE (DATEPART(WEEKDAY, GETDATE()) + ##DATEFIRST) % 7
WHEN 1 THEN -2
WHEN 2 THEN -3
ELSE -1
END, DATEDIFF(DAY, 0, GETDATE()));
This will work for all language and DATEFIRST settings.
This function returns last working day and takes into account holidays and weekends. You will need to create a simple holiday table.
-- =============================================
-- Author: Dale Kilian
-- Create date: 2019-04-29
-- Description: recursive function returns last work day for weekends and
-- holidays
-- =============================================
ALTER FUNCTION dbo.fnGetWorkWeekday
(
#theDate DATE
)
RETURNS DATE
AS
BEGIN
DECLARE #importDate DATE = #theDate
DECLARE #returnDate DATE
--Holidays
IF EXISTS(SELECT 1 FROM dbo.Holidays WHERE isDeleted = 0 AND #theDate = Holiday_Date)
BEGIN
SET #importDate = DATEADD(DAY,-1,#theDate);
SET #importDate = (SELECT dbo.fnGetWorkWeekday(#importDate))
END
--Satruday
IF(DATEPART(WEEKDAY,#theDate) = 7)
BEGIN
SET #importDate = DATEADD(DAY,-1,#theDate);
SET #importDate = (SELECT dbo.fnGetWorkWeekday(#importDate))
END
--Sunday
IF(DATEPART(WEEKDAY,#theDate) = 1)
BEGIN
SET #importDate = DATEADD(DAY,-2,#theDate);
SET #importDate = (SELECT dbo.fnGetWorkWeekday(#importDate))
END
RETURN #importDate;
END
GO
Then how about:
declare #dt datetime='1 dec 2012'
select case when 8-##DATEFIRST=DATEPART(dw,#dt)
then DATEADD(d,-2,#dt)
when (9-##DATEFIRST)%7=DATEPART(dw,#dt)%7
then DATEADD(d,-3,#dt)
else DATEADD(d,-1,#dt)
end
The simplest solution to find the previous business day is to use a calendar table with a column called IsBusinessDay or something similar. The your query is something like this:
select max(BaseDate)
from dbo.Calendar c
where c.IsBusinessDay = 0x1 and c.BaseDate < #InputDate
The problem with using functions is that when (not if) you have to create exceptions for any reason (national holidays etc.) the code quickly becomes unmaintainable; with the table, you just UPDATE a single value. A table also makes it much easier to answer questions like "how many business days are there between dates X and Y", which are quite common in reporting tasks.
You can easily make this a function call, adding a second param to replace GetDate() with whatever date you wanted.
It will work for any day of the week, at any date range, if you change GetDate().
It will not change the date if the day of week is the input date (GetDate())
Declare #DayOfWeek As Integer = 2 -- Monday
Select DateAdd(Day, ((DatePart(dw,GetDate()) + (7 - #DayOfWeek)) * -1) % 7, Convert(Date,GetDate()))
More elegant:
select DATEADD(DAY,
CASE when datepart (dw,Getdate()) < 3 then datepart (dw,Getdate()) * -1 + -1 ELSE -1 END,
cast(GETDATE() as date))
select
dateadd(dd,
case DATEPART(dw, getdate())
when 1
then -2
when 2
then -3
else -1
end, GETDATE())
thanks for the tips above, I had a slight variant on the query in that my user needed all values for the previous business date. For example, today is a Monday so he needs everything between last Friday at midnight through to Saturday at Midnight. I did this using a combo of the above, and "between", just if anyone is interested. I'm not a massive techie.
-- Declare a variable for the start and end dates.
declare #StartDate as datetime
declare #EndDate as datetime
SELECT #StartDate = DATEADD(DAY, CASE DATENAME(WEEKDAY, GETDATE())
WHEN 'Sunday' THEN -2
WHEN 'Monday' THEN -3
ELSE -1 END, DATEDIFF(DAY, 0, GETDATE()))
select #EndDate = #StartDate + 1
select #StartDate , #EndDate
-- Later on in the query use "between"
and mydate between #StartDate and #EndDate

T-SQL - Get start and end date based on week number.

Our business considers a week from (Monday - Sunday). I need to write a T-SQL function, which passes in year, week no as parameters and it will return the start and end date of that week. However I've seen many examples but the problem lies within the year overlapping.
e.g December 26, 2011 (Monday) - January 01, 2012 (Sunday)... << Would want to consider this as the last week of 2011.
And also in T-SQL the datepart(ww,DATE) considers Sunday as the start of the week??
Or Am I better creating my own table with the week no and storing its start and end date?
DECLARE
#Year INT,
#Week INT,
#FirstDayOfYear DATETIME,
#FirstMondayOfYear DATETIME,
#StartDate DATETIME,
#EndDate DATETIME
SET #Year = 2011
SET #Week = 52
-- Get the first day of the provided year.
SET #FirstDayOfYear = CAST('1/1/' + CAST(#YEAR AS VARCHAR) AS DATETIME)
-- Get the first monday of the year, then add the number of weeks.
SET #FirstMondayOfYear = DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, 6 - DATEPART(DAY, #FirstDayOfYear), #FirstDayOfYear)), 0)
SET #StartDate = DATEADD(WEEK, #Week - 1, #FirstMondayOfYear)
-- Set the end date to one week past the start date.
SET #EndDate = DATEADD(WEEK, 1, #StartDate)
SELECT #StartDate AS StartDate, DATEADD(SECOND, -1, #EndDate) AS EndDate
You should create a table with the holidays and days you donĀ“t wnat to consider in your counts.
After this count the days between the initial date and final date. (Step1)
Select in your table to check how many days are between your ini and final dates. (Step2)
Finally subtract the result of step 2 with result of step 1;
This is the sort of thing where you're better off creating a calendar table: the main issue is knowing how far into the past/future to populate it, but beyond that, have the table schema include week number and date. Depending on what other date-based queries you want to do, you might want to have additional column to break the date down into its constituant parts (e.g., have three separate columns for day/month/year/name of day, etc).
How about this one:
--DROP FUNCTION dbo.GetBusinessWeekStart
CREATE FUNCTION dbo.GetBusinessWeekStart(
#Year SMALLINT,
#Week TINYINT
)
RETURNS DATETIME
AS
BEGIN
DECLARE #FirstMonday TINYINT
DECLARE #Result DATETIME
IF ISNULL(#Week,0)<1 OR ISNULL(#Year,0)<1900
BEGIN
SET #Result= NULL;
END
ELSE
BEGIN
SET #FirstMonday=1
WHILE DATEPART(dw,CONVERT(DATETIME, '01/0' + CONVERT(VARCHAR,#FirstMonday) + '/' + CONVERT(VARCHAR,#Year)))<>2
BEGIN
SET #FirstMonday=#FirstMonday+1
END
SET #Result=CONVERT(DATETIME, '01/0' + CONVERT(VARCHAR,#FirstMonday) + '/' + CONVERT(VARCHAR,#Year))
SET #Result=DATEADD(d,(#Week-1)*7,#Result)
IF DATEPART(yyyy,#Result)<>#Year
BEGIN
SET #Result= NULL;
END
END
RETURN #Result
END
GO
--Example
SELECT dbo.GetBusinessWeekStart(2011,15) [Start],dbo.GetBusinessWeekStart(2011,15)+6 [End]

How to get date difference between two dates in same year with one date is from an input date not from the year

Well this is my case: I have an input date X (dd-mm-yyyy), and I want to count the number of days between it with the year part is changed into current year and today's date in SQL. I t comes with the following condition, after the year is changed temporarily: (Here's my current idea of the logic)
- If date X is earlier than today, then difference = datediff(X,now), with the X year is current year
- If date X is later than today, then difference = datediff(X,now), with the X year is one year before
Sample case:
1st case: The input date is 6-6-1990. Today (automatically generated) is 22-8-2011. Then the difference will be = datediff(6-6-2011,22-08-2011)
2nd case: The input date is 10-10-1990. Today (automatically generated) is 22-8-2011. Then the difference will be = datediff(10-10-2010,22-08-2011)
Any idea how to do this in SQL (in SQL Server)? Or is there any other more simple alternatives for this problem? I'd also like this to be done in the query and not using a stored procedure or function
Sorry if there's already a similar question, I just don't know the exact keyword for this problem :( if there's a question like this previously, feel free to direct me there.
Thanks in advance
Here is the implementation (if I understood the logic you need correctly):
USE YourDbName
GO
CREATE FUNCTION YearPartDiff (#date datetime)
RETURNS int
AS
BEGIN
DECLARE #dateCurrentYear datetime
SET #dateCurrentYear = DATEADD(year, YEAR(GETDATE()) - YEAR(#date), #date)
DECLARE #result int
IF #dateCurrentYear < GETDATE()
SET #result = ABS(DATEDIFF(day, #dateCurrentYear, GETDATE()))
ELSE
SET #result = ABS(DATEDIFF(day, DATEADD(year, -1, #dateCurrentYear), GETDATE()))
RETURN(#result)
END
GO
And the example of usage:
USE YourDbName
GO
DECLARE #someDate datetime
SET #someDate = '2011-06-06'
SELECT dbo.YearPartDiff(#someDate) /*returns 77*/
SET #someDate = '2010-10-10'
SELECT dbo.YearPartDiff(#someDate) /*returns 316*/
Basically, #Andrei's solution, but in a single statement:
SELECT
DayDiff = DATEDIFF(
DAY,
DATEADD(YEAR, CASE WHEN LastOcc > GETDATE() THEN -1 ELSE 0 END, LastOcc),
GETDATE()
)
FROM (
SELECT LastOcc = DATEADD(YEAR, YEAR(GETDATE()) - YEAR(#InputDate), #InputDate)
) s
This seems to do the job
SELECT DATEDIFF(DAY, CONVERT(DATETIME, N'2011-06-06'), CONVERT(DATETIME, N'2011-08-22'))
So the basic syntax is
SELECT DATEDIFF(DAY, CONVERT(DATETIME, N'yyyy-mm-dd'), CONVERT(DATETIME, N'yyyy-mm-dd '))
Alternatively, you can use GETDATE() instead of the string for today's date
I have used "SELECT DATEDIFF( D, "+myDate+", GETDATE())" in my code, on SQL Server 2005. It works for me. The value myDate of course would be the DateTime input value.
you should try this query:
create table #T (inp_date datetime)
insert #T values ('06-06-1990')
insert #T values ('08-22-1990')
insert #T values ('10-10-1990')
--select * from #T
select inp_date, GETDATE(),
CASE
WHEN DATEADD(yy,DATEDIFF(yy,inp_date,GETDATE()),inp_date) <= GETDATE()
THEN DATEDIFF(dd,DATEADD(yy,DATEDIFF(yy,inp_date,GETDATE()),inp_date),GETDATE())
ELSE DATEDIFF(dd,DATEADD(yy,DATEDIFF(yy,inp_date,GETDATE())-1,inp_date),GETDATE())
END
from #T