How to get all dates between two dates in sql server - sql

I want to get all dates between startend and Enddate.I used between to get the desired result. But the between function skipping the current date.
Declare #StartDate Datetime ='2014-04-01 11:13:37'
,#EndDate datetime ='2014-04-04 11:13:37'
Query:-
Select * from table where date between #Startdate and #EndDate
Current Result:-
2014-04-02 11:13:37
2014-04-03 11:13:37
2014-04-04 11:13:37
Expected result:-
2014-04-01 11:13:37
2014-04-02 11:13:37
2014-04-03 11:13:37
2014-04-04 11:13:37

You could create a procedure like this:
CREATE PROCEDURE getAllDaysBetweenTwoDate
(
#StartDate DATETIME,
#EndDate DATETIME
)
AS
BEGIN
DECLARE #TOTALCount INT
SET #StartDate = DATEADD(DAY,-1,#StartDate)
Select #TOTALCount= DATEDIFF(DD,#StartDate,#EndDate);
WITH d AS
(
SELECT top (#TOTALCount) AllDays = DATEADD(DAY, ROW_NUMBER()
OVER (ORDER BY object_id), REPLACE(#StartDate,'-',''))
FROM sys.all_objects
)
SELECT AllDays From d
RETURN
END
GO
Courtesy: Find All the Days Between Two Dates

Your query works for me perfectly.
DECLARE #StartDate DATETIME = '2014-04-01 11:13:37',
#EndDate DATETIME = '2014-04-04 11:13:37';
WITH cte_dates
AS
(
SELECT DATEADD(MONTH,-1,#startDate) dates --get dates from a month before start date
UNION ALL
SELECT DATEADD(DAY,1,dates)
FROM cte_dates
WHERE dates < DATEADD(MONTH,1,#EndDate) --up to a month after end date
)
SELECT dates
FROM cte_dates
WHERE dates BETWEEN #Startdate AND #EndDate
Results:
dates
-----------------------
2014-04-01 11:13:37.000
2014-04-02 11:13:37.000
2014-04-03 11:13:37.000
2014-04-04 11:13:37.000
This means that it's probably an issue with your data, specifically the time section. If you don't need to look at time and only need specific dates, try this instead:
DECLARE #StartDate DATE = '2014-04-01',
#EndDate DATE = '2014-04-04';
SELECT *
FROM yourTable
WHERE CAST([date] AS DATE) BETWEEN #startDate AND #EndDate

You Can Try this
Declare #StartDate Date ='2014-04-01'
,#EndDate date ='2014-04-04'
(OR)
Declare #StartDate Datetime ='2014-04-01 00:00:00'
,#EndDate datetime ='2014-04-04 12:59:59'
Query:-
Select * from table where date between #Startdate and #EndDate

Related

Know what the following SQL code is doing

What does the following code do??
Declare #StartDate datetime; -- figure
Declare #EndDate datetime; -- figure
Declare #CurrentDate datetime
Set #CurrentDate = #StartDate
While #CurrentDate <= #EndDate
Begin
Insert Into dbo.Tbl_Time_Dimension
Values (#CurrentDate,
year(#CurrentDate),
datepart(Quarter, #CurrentDate),
month(#CurrentDate),
datepart(week, #CurrentDate),
day(#CurrentDate))
Select #CurrentDate = DateAdd(dd, 1, #CurrentDate)
End
This code will iterate from #StartDate to #EndDate skipping by day and will insert a row into a table called Tbl_Time_Dimension.
The fields being saved into this table are : Date, Year, Quarter, Month, Week and Day for each date in the date range.
Declare #StartDate datetime; --figure
Declare #EndDate datetime; --figure
Declare #CurrentDate datetime
-- Starts the iterator on #StartDate
Set #CurrentDate=#StartDate
-- Iterates until #EndDate
While #CurrentDate<=#EndDate
Begin
-- Saves data in table
Insert Into dbo.Tbl_Time_Dimension
Values (#CurrentDate, year(#CurrentDate),
datepart(Quarter,#CurrentDate),
month(#CurrentDate),
datepart(week,#CurrentDate),
day(#CurrentDate))
-- Increments the date by 1 day
Select #CurrentDate=DateAdd(dd,1,#CurrentDate)
End
this query gets two date
and for each day between startdate and enddate insert that date into Tbl_Time_Dimension as well as it's month , week , Day and quarter

Sql Server- Get the dates from the database between the range supplied

I have an issue to get the records if the FtableID at any point in the range (Start date and End date) has a StatusID=2.
My table Structure is
ID FTableID StatusID AddedOn
75324 53591 1 2019-03-17 06:48:14.490
75325 53591 2 2019-03-18 06:48:14.663
75326 53591 3 2019-03-19 06:54:20.830
#StartDate Datetime='2019/03/17 23:00:00' ,
#EndDate Datetime='2019/03/20 23:59:59'
Select ID, FTableID,StatusID,AddedOn from MyTableName where FTableID=53591
And StatusID=2 and AddedOn <= #EndDate
I know my query is wrong and it gives the record even when I pass the #startdate after its status gets changed to 3 (Completed)
I am confused to set the start date filter.
I need to check if this FtableID record is in status id =2 at any point in the range supplied
The record should come If I pass the #StartDate Datetime='2019/03/18 23:00:00', #EndDate Datetime='2019/03/20 23:59:59' because it is in this range it was in the status=2
The record should not come If I pass the #StartDate Datetime='2019/03/19 23:00:00', #EndDate Datetime='2019/03/20 23:59:59' because it was convertted to statusID=3
Please suggest me on this. Thanks in advance.
use this
select *
from YourTableName
where AddedOn between (#StartDate and #EndDate)
and StatusID=2
One method uses exists.
I would simplify your date arithmetic as well, so:
declare #StartDate datetime '2019-03-17 23:00:00';
declare #EndDate datetime = '2019-03-20'
select t.*
from mytablename t
where exists (select 1
from mytablename t2
where t2.ftableid = t.ftableid and
t2.statusid = 2 and
t2.AddedOn >= #StartDate and
t2.AddedOn < #EndDate
);

Having issues with dates in SQL

I'm writing a report that needs to collect data each day, between 0900hs and 1700hs.
I thought it would be fine as follows:
cast(convert(char(8),t.trxtime,112)as time)
between CONVERT(VARCHAR(5),getdate(),108) >= '09:00'
and CONVERT(VARCHAR(5),getdate(),108) < '17:00'
....BUT no cigar.
Thank you!!!
Hmmm, you could just use datepart():
where datepart(hour, t.trxtime) between 9 and 16 and
cast(t.trxtime as date) = cast(getdate() as date)
I'm not sure if the date comparison is actually necessary.
You could do something like this (assuming you mean actually for the current date, and not for every date in a range:
declare #startDate datetime
declare #endDate datetime
select #startDate = '2014-11-03 09:00:00',
#endDate = '2014-11-03 17:00:00'
select *
from table
where myDate between #startDate and #endDate
if you did mean between 0900 and 1700 for each day, you could do:
declare #startDate datetime
declare #endDate datetime
select #startDate = '2014-10-03',
#endDate = '2014-11-03' -- note i'm still limiting it to a range of ~1 month
select *
from table
where myDate between #startDate and #endDate
and datepart(hour, myDate) between 9 and 17

tsql: How to retrieve the last date of each month between given date range

I have two date for example 08/08/2013 and 11/11/2013 and I need last date of each month starting from August to November in a table so that i can iterate over the table to pick those dates individually.
I know how to pick last date for any month but i am stucked with a date range.
kindly help, it will be highly appreciated.
Note : I am using Sql 2008 and date rang could be 1 month , 2 month or 6 month or a year or max too..
You can use CTE for getting all last days of the month within the defined range
Declare #Start datetime
Declare #End datetime
Select #Start = '20130808'
Select #End = '20131111'
;With CTE as
(
Select #Start as Date,Case When DatePart(mm,#Start)<>DatePart(mm,#Start+1) then 1 else 0 end as [Last]
UNION ALL
Select Date+1,Case When DatePart(mm,Date+1)<>DatePart(mm,Date+2) then 1 else 0 end from CTE
Where Date<#End
)
Select * from CTE
where [Last]=1 OPTION ( MAXRECURSION 0 )
DECLARE #tmpTable table (LastDates DATE);
DECLARE #startDate DATE = '01/01/2012'; --1 Jan 2012
DECLARE #endDate DATE = '05/31/2012'; --31 May 2012
DECLARE #tmpEndDate DATE;
SET #startDate = DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#startDate)+1,1));
SET #tmpEndDate = DATEADD(DAY, 1, #endDate);
WHILE (#startDate <= #tmpEndDate)
BEGIN
INSERT INTO #tmpTable (LastDates) values (DATEADD(DAY, -1, #startDate));
SET #startDate = DATEADD(MONTH, 1, #startDate);
END
SELECT [LastDates] FROM #tmpTable;
Output:
Example: 1
#startDate DATE = '01/01/2012'; --1 Jan 2012
#endDate DATE = '05/31/2012'; --31 May 2012
LastDates
----------
2012-01-31
2012-02-29
2012-03-31
2012-04-30
2012-05-31
Example: 2
#startDate DATE = '11/01/2011'; --1 Nov 2011
#endDate DATE = '03/13/2012'; --13 Mar 2012
LastDates
----------
2011-11-30
2011-12-31
2012-01-31
2012-02-29
I've created a table variable, filled it with all days between #startDate and #endDate and searched for max date in the month.
declare #tmpTable table (dates date)
declare #startDate date = '08/08/2013'
declare #endDate date = '11/11/2013'
while #startDate <= #endDate
begin
insert into #tmpTable (dates) values (#startDate)
set #startDate = DATEADD(DAY, 1, #startDate)
end
select max(dates) as [Last day] from #tmpTable as o
group by datepart(YEAR, dates), datepart(MONTH, dates)
Results:
Last day
2013-08-31
2013-09-30
2013-10-31
2013-11-11
To also get last day of November this can be used before loop:
set #endDate = DATEADD(day, -1, DATEADD(month, DATEDIFF(month, 0, #endDate) + 1, 0))
Following script demonstrates the script to find last day of previous, current and next month.
----Last Day of Previous Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0))
LastDay_PreviousMonth
----Last Day of Current Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+1,0))
LastDay_CurrentMonth
----Last Day of Next Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+2,0))
LastDay_NextMonth
If you want to find last day of month of any day specified use following script.
--Last Day of Any Month and Year
DECLARE #dtDate DATETIME
SET #dtDate = '8/18/2007'
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#dtDate)+1,0))
LastDay_AnyMonth
ResultSet:
LastDay_AnyMonth
Source - SQL Server Central.
You can use a recursive CTE to do this, note the MAXRECURSION OPTION prevents an infinite loop:
DECLARE #StartDate DATE = '2013-08-08'
DECLARE #EndDate DATE = '2013-11-11'
;WITH dateCTE
AS
(
SELECT CAST(DATEADD(M, 1,DATEADD(d, DAY(#StartDate) * -1, #StartDate)) AS DATE) EndOFMonth
UNION ALL
SELECT CAST(DATEADD(M, 2,DATEADD(d, DAY(EndOFMonth) * -1, EndOFMonth)) AS DATE)
FROM dateCTE
WHERE EndOFMonth < DATEADD(d, DAY(#EndDate) * -1, #EndDate)
)
SELECT *
FROM dateCTE
OPTION (MAXRECURSION 30);
This returns
EndOFMonth
----------
2013-08-31
2013-09-30
2013-10-31
try this
the last row(where) is optional for date filtering
declare #table table
(
thisdate date
)
insert into #table values ('12/01/2013'),('05/06/2013'),('04/29/2013'),('02/20/2013')
select *,DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,thisdate)+1,0))
LastDay from #table
where thisdate between 'givendate' and 'givendate'
The Example Below is for all dates
thisdate lastday
2013-12-01 2013-12-31 23:59:59.000
2013-05-06 2013-05-31 23:59:59.000
2013-04-29 2013-04-30 23:59:59.000
2013-02-20 2013-02-28 23:59:59.000
The following CTE gives you the last day of every month from February 1900 until the middle of the 26th century (on my machine):
;with LastDaysOfMonths as (
select DATEADD(month,
ROW_NUMBER() OVER (ORDER BY so.object_id),
'19000131') as Dt
from sys.objects so,sys.objects so1
)
select * from LastDaysOfMonths
It should be easy enough to use it as part of a larger query or to filter it down to just the dates you want. You can adjust the range of years as needed by changing the constant 19000131. The only important thing to do is make sure that you use a month that has 31 days in it and always have the constant be for day 31.
No need to use a common table expression or anything like that - this simple query will do it:
SELECT DATEADD(d, -1, DATEADD(mm, DATEDIFF(m, 0, DATEADD(m, number, '2013-08-08')) + 1, 0)) AS EndOfMonth
FROM master.dbo.spt_values
WHERE 'P' = type
AND DATEADD(m, number, '2013-08-08') < '2013-11-11';
Although the question is about the last day which #bummi has already answered.
But here is the solution for the first date which might be helpful for someone.
Get the first dates of all the months in-between the #FromDate and #ToDate.
DECLARE #FromDate DATETIME = '2019-08-13'
DECLARE #ToDate DATETIME = '2019-11-25'
;WITH CTE
AS
(
SELECT DATEADD(DAY, -(DAY(#FromDate) - 1), #FromDate) AS FirstDateOfMonth
UNION ALL
SELECT DATEADD(MONTH, 1, FirstDateOfMonth)
FROM CTE
WHERE FirstDateOfMonth < DATEADD(DAY, -(DAY(#ToDate) - 1), #ToDate)
)
SELECT * FROM CTE
Here is the result
--Result
2019-08-01 00:00:00.000
2019-09-01 00:00:00.000
2019-10-01 00:00:00.000
2019-11-01 00:00:00.000

Easiest way to populate a temp table with dates between and including 2 date parameters

What is the easiest way to populate a temp table with dates including and between 2 date parameters. I only need the 1st day of the month dates.
So for example if #StartDate = '2011-01-01' and #EndDate = '2011-08-01'
Then I want this returned in the table
2011-01-01
2011-02-01
2011-03-01
2011-04-01
2011-05-01
2011-06-01
2011-07-01
2011-08-01
This works even if the #StartDate is not the first of the month. I'm assuming that if it's not the start of the month, you want to begin with the first of the next month. Otherwise remove the +1.:
;WITH cte AS (
SELECT CASE WHEN DATEPART(Day,#StartDate) = 1 THEN #StartDate
ELSE DATEADD(Month,DATEDIFF(Month,0,#StartDate)+1,0) END AS myDate
UNION ALL
SELECT DATEADD(Month,1,myDate)
FROM cte
WHERE DATEADD(Month,1,myDate) <= #EndDate
)
SELECT myDate
FROM cte
OPTION (MAXRECURSION 0)
declare #StartDate date = '2014-01-01';
declare #EndDate date = '2014-05-05';
;WITH cte AS (
SELECT #StartDate AS myDate
UNION ALL
SELECT DATEADD(day,1,myDate) as myDate
FROM cte
WHERE DATEADD(day,1,myDate) <= #EndDate
)
SELECT myDate
FROM cte
OPTION (MAXRECURSION 0)
declare #StartDate datetime
declare #EndDate datetime
select #StartDate = '2011-01-01' , #EndDate = '2011-08-01'
select #StartDate= #StartDate-(DATEPART(DD,#StartDate)-1)
declare #temp table
(
TheDate datetime
)
while (#StartDate<=#EndDate)
begin
insert into #temp
values (#StartDate )
select #StartDate=DATEADD(MM,1,#StartDate)
end
select * from #temp
Works even if the #StartDate is not the first day of the month by going back to the initial day of the month of StartDate
this is tested in SQL 2008 R2
Declare #StartDate datetime = '2015-03-01'
Declare #EndDate datetime = '2015-03-31'
declare #temp Table
(
DayDate datetime
);
WHILE #StartDate <= #EndDate
begin
INSERT INTO #temp (DayDate) VALUES (#StartDate);
SET #StartDate = Dateadd(Day,1, #StartDate);
end ;
select * from #temp
Result:
DayDate
-----------------------
2015-03-01 00:00:00.000
2015-03-02 00:00:00.000
2015-03-03 00:00:00.000
2015-03-04 00:00:00.000
...
Interestingly, it is faster to create from enumerated data as per this article.
DECLARE #StartDate DATE = '10001201';
DECLARE #EndDate DATE = '20000101';
DECLARE #dim TABLE ([date] DATE)
INSERT #dim([date])
SELECT d
FROM
(
SELECT
d = DATEADD(DAY, rn - 1, #StartDate)
FROM
(
SELECT TOP (DATEDIFF(DAY, #StartDate, #EndDate))
rn = ROW_NUMBER() OVER (ORDER BY s1.[object_id])
FROM
sys.all_objects AS s1
CROSS JOIN
sys.all_objects AS s2
ORDER BY
s1.[object_id]
) AS x
) AS y;
On my machine, it's around 60% faster with large date ranges. The recursion method can populate 2000 years worth of data in around 3 seconds though, and looks a lot nicer, so I don't really recommend this method just for incrementing days.
Correction for null dates:
IF OBJECT_ID('tempdb..#dim') IS NOT NULL
DROP TABLE #dim
CREATE TABLE #dim ([date] DATE)
if not #Begin_Date is null and not #End_Date is null
begin
INSERT #dim([date])
SELECT d
FROM(
SELECT
d = DATEADD(DAY, rn - 1, #Begin_Date)
FROM
(
SELECT TOP (DATEDIFF(DAY, #Begin_Date, #End_Date))
rn = ROW_NUMBER() OVER (ORDER BY s1.[object_id])
FROM
sys.all_objects AS s1
CROSS JOIN
sys.all_objects AS s2
ORDER BY
s1.[object_id]
) AS x
) AS y;
end
CREATE TABLE #t (d DATE)
INSERT INTO #t SELECT GETDATE()
GO
INSERT #t SELECT DATEADD(DAY, -1, MIN(d)) FROM #t
GO 10