SQL query to check availability on an event table - sql

I have a table of events with the columns Room Number and Date
I want to check availability in a certain room so I tried creating a temp calendar table just to compare, but I know I'm doing something wrong with my left join so I need some pointers to help me achieve my goal: only show the dates where there is no event in the specific room.
This is my query so far:
IF OBJECT_ID('tempdb..#calendarTable') IS NOT NULL
DROP TABLE #calendarTable;
GO
CREATE TABLE #calendarTable (
"DayID" INT
,"DayDate" DATE
,PRIMARY KEY (DayID)
)
DECLARE #startDate AS DATE
DECLARE #baseDate DATE
,#offSet INT
,#numberOfLoops INT
SET #startDate = GETDATE() /*'20150101'*/
SET #baseDate = #startDate
SET #offSet = 0
SET #numberOfLoops = DATEDIFF(DAY, #baseDate, DATEADD(MONTH, 24, #baseDate)) /*365*/
WHILE (#offSet < #numberOfLoops)
BEGIN
INSERT INTO #calendarTable (
"DayID"
,"DayDate"
)
SELECT (#offSet + 1)
,DATEADD(DAY, #offSet, #baseDate)
SET #offSet = #offSet + 1
END
SELECT TOP (500)
DayDate
,a.Arrangement_Number
,a.Activity
,a.Room_Number
FROM #calendarTable
left outer join [Events] as a ON DayDate = (convert(varchar(10), a.[Date],120))
where Room_Number = 53
order by DayDate asc

Related

SQL Query, bring data between 2 dates with limitation

In SQL, I am going to write a query which insert all data between 2 dates and also I want to bring then in a 1000 batch but since the number of data between those days are more than my limitation I was going to write a loop which makes the smaller period to bring the data.
here is my code:
DECLARE #StartDate DATETIME = CAST('2021-06-02 01:00:00.000' AS DATETIME)
DECLARE #EndDate DATETIME = CAST('2021-06-23 01:00:00.000' AS DATETIME)
DECLARE #RealRowCount INT = (SELECT DISTINCT SUM(##ROWCOUNT) OVER() FROM GetReport (
#StartDate, #EndDate))
DECLARE #TransactionCount INT = (SELECT DISTINCT TransactionCount FROM GetReport (
#StartDate, #EndDate))
WHILE #RealRowCount < #TransactionCount
BEGIN
DECLARE #DiffDate INT = (SELECT DATEDIFF(DAY, #StartDate, #EndDate))
SET #EndDate = DATEADD(DAY, #DiffDate/2 ,#StartDate)
SELECT *,#StartDate, #EndDate FROM GetReport (#StartDate, #EndDate)
END
PS: I was thinking about find the middle of the period of date and then change them into the new EneDate and StartDate but there is problem here!
Your question is not very clear. Suppose you have 10,000 records between two dates and you do not want to retrieve more than a thousand records at a time. In this case, you can use pagination. Both in the program code and in SQL.
DECLARE #StartDate DATETIME = CAST('2021-06-02 01:00:00.000' AS DATETIME)
DECLARE #EndDate DATETIME = CAST('2021-06-23 01:00:00.000' AS DATETIME)
DECLARE #RealRowCount INT = (SELECT DISTINCT COUNT(*) FROM Products WHERE InsertDate BETWEEN #StartDate AND #EndDate)
DECLARE #Counter INT = 0
WHILE #Counter <= #RealRowCount
BEGIN
SELECT *
FROM Products
WHERE InsertDate BETWEEN #StartDate AND #EndDate
ORDER BY InsertDate
OFFSET #Counter ROWS -- skip #Counter rows
FETCH NEXT 1000 ROWS ONLY -- take 1000 rows
SET #Counter = #Counter + 1000
END
Or you can get the time difference between the two dates and add the start date each time in a specific step and retrieve the data of that date.
For example, the date difference is 20 days. Increase the start date by 5 steps each time to the start date with the end date
I create another table to put Dates and if this table has any rows I can get 'EndDate', but if it has not any records I simply just use the date that I specified.
AccSync is the table that I insert details of my records and AccTransformation is the table wich I want to insert all of my records.
DECLARE #Count INT = (SELECT COUNT(*) FROM [AccTransaction])
DECLARE #Flag BIT = (SELECT IIF(#Count > 1, 1, 0))
DECLARE #End DATETIME = GETDATE();
DECLARE #Start DATETIME
IF(#Flag = 0)
BEGIN
SET #Start = CAST('2021-03-08' AS DATETIME2);
SET #Flag = 1
END
ELSE IF(#Flag = 1)
BEGIN
SET #Start = (SELECT TOP 1 EndDate FROM (SELECT EndDate FROM [AccSync] ORDER BY ActionDate DESC OFFSET 0 ROW) AS TT);
END
DECLARE #RealRowCount INT = (SELECT DISTINCT SUM(##ROWCOUNT) FROM [GetReport] (#Start, #End));
DECLARE #TransactionCount INT = (SELECT DISTINCT TransactionCount FROM [GetReport] (#Start, #End));
----------------------------------------------------------------------------------------------
WHILE (#RealRowCount <> #TransactionCount)
BEGIN
DECLARE #DiffDate INT = (SELECT DATEDIFF(SECOND, #Start, #End))
SET #End = DATEADD(SECOND, (#DiffDate/2), #Start)
SET #RealRowCount = (SELECT DISTINCT SUM(##ROWCOUNT) FROM [GetReport] (#Start, #End))
SET #TransactionCount = (SELECT DISTINCT TransactionCount FROM [GetReport] (#Start, #End))
END
----------------------------------------------------------------------------------------------
INSERT INTO [AccTransaction]
SELECT *
FROM [GetReport](#Start, #End)
----------------------------------------------------------------------------------------------
INSERT INTO [AccSync]
VALUES(NEWID(), GETDATE(), #Start, #End, ISNULL(#TransactionCount,0), DATEDIFF(SECOND, #Start, #End))

Looping distinct values from one table through another without a join

I know looping is not ideal in SQL, but I couldn't think of another way of doing this.
I want each distinct row from this Table 1 to have each distinct date and hour produced on Table 2.
In other words, Table 2 has the dates between 05/01/2014 through 04/30/2015, with each distinct date having 24 rows, one for each hour of the day. I now want each distinct row in Table 1 to have each distinct date on Table 2, with each of its 24 hours.
Table 1:
DROP TABLE Baylor_Raw..MEDICAL_SERVICE_DESC
SELECT MEDICAL_SERVICE_DESC
INTO Baylor_Raw..MEDICAL_SERVICE_DESC
FROM Baylor_Raw..Raw_ADT
WHERE MEDICAL_SERVICE_DESC IS NOT NULL AND MEDICAL_SERVICE_DESC NOT IN ('#N/A','CANCEL','DAY SURGERY','HOSPICE','INFUSION')
Table 2:
DECLARE #DATE DATE
SET #DATE = '05/01/2014'
DECLARE #HOUR INT
SET #HOUR = 0
DROP TABLE Baylor_Raw..DateTable
CREATE TABLE Baylor_Raw..DateTable
(DATE_OF_DISCHARGE DATE
,HOUR_OF_DISCHARGE INT)
WHILE #DATE<'05/01/2015' BEGIN
WHILE #HOUR<25 BEGIN
INSERT INTO Baylor_Raw..DateTable (DATE_OF_DISCHARGE,HOUR_OF_DISCHARGE)
VALUES (#DATE,#HOUR)
SET #HOUR = #HOUR+1
END
SET #DATE = DATEADD(DD,1,#DATE)
SET #HOUR = 0
END
This below attempt did not work. I canceled after the run time exceeded several minutes.
DECLARE #MEDICAL_SERVICE_DESC NVARCHAR(255)
SET #MEDICAL_SERVICE_DESC = (SELECT MIN(MEDICAL_SERVICE_DESC) FROM Baylor_Raw..MEDICAL_SERVICE_DESC)
DECLARE #DATE DATE
SET #DATE = '05/01/2014'
DECLARE #HOUR INT
SET #HOUR = 0
DROP TABLE Baylor_Raw..DateTable
CREATE TABLE Baylor_Raw..DateTable
(MEDICAL_SERVICE_DESC NVARCHAR,
DATE_OF_DISCHARGE DATE
,HOUR_OF_DISCHARGE INT)
WHILE #MEDICAL_SERVICE_DESC IS NOT NULL BEGIN
WHILE #DATE<'05/01/2015' BEGIN
WHILE #HOUR<25 BEGIN
INSERT INTO Baylor_Raw..DateTable (MEDICAL_SERVICE_DESC,DATE_OF_DISCHARGE,HOUR_OF_DISCHARGE)
VALUES (#MEDICAL_SERVICE_DESC,#DATE,#HOUR)
SET #HOUR = #HOUR+1
END
SET #DATE = DATEADD(DD,1,#DATE)
SET #HOUR = 0
END
DELETE FROM Baylor_Raw..MEDICAL_SERVICE_DESC WHERE MEDICAL_SERVICE_DESC = #MEDICAL_SERVICE_DESC
SET #MEDICAL_SERVICE_DESC = (SELECT MIN(MEDICAL_SERVICE_DESC) FROM Baylor_Raw..MEDICAL_SERVICE_DESC)
SET #DATE = '05/01/2014'
END
So you want all distinct records from table1 paired with all records in table2? That is a cross join:
select *
from (select distinct * from table1) t1
cross join table2;
Or do you want them related by date? Then inner-join:
select *
from (select distinct * from table1) t1
inner join table2 t2 on t1.date = t2.date;
You might get better performance from building lists of dates and hours using loops first, and then combining it with the service names just one time using a cross join, something like this. You may need to tweak it a bit because you understand the source data:
DECLARE #dates TABLE (DATE DATE)
DECLARE #hours TABLE (hours INT)
DECLARE #hour INT
,#date DATE
SET #hour = 0
SET #date = '05/01/2014'
WHILE (#hour < 25)
BEGIN
INSERT INTO #hours
SELECT #hour
SET #hour = #hour + 1
END
WHILE (# DATE < '05/01/2015')
BEGIN
INSERT INTO #dates
SELECT #date
SET #DATE = DATEADD(DD, 1, #DATE)
END
INSERT INTO Baylor_Raw..DateTable (
MEDICAL_SERVICE_DESC
,DATE_OF_DISCHARGE
,HOUR_OF_DISCHARGE
)
SELECT MEDICAL_SERVICE_DESC
,DATE
,hour
FROM Baylor_Raw..MEDICAL_SERVICE_DESC
CROSS JOIN #date d
CROSS JOIN #hours h

Displaying the number of valid results for a range of dates

I currently have a table with a creation date and a expiry date. I currently have a sql command to get the number of valid items for a given date.
select
count(id) ,CONVERT(date, getdate())
from
table
where
createDate < getdate() and expDate > getdate()
This returns the count and current date.
Is it possible to wrote a sql query that will return the result for a range of dates, say I if wanted to plot the number of valid items over a range of 15 days?
Thanks!
Try this:
create table #datelist (ValidDateCheck date, ValidResults int)
declare #startdate date = '1/1/2015'
declare #enddate date = '2/1/2015'
declare #interval int = 1 --Use 1 if you want every day between your dates, use 2 if you want every other day, etc.
declare #datecounter date = #startdate
declare #count int
while #datecounter <= #enddate
begin
set #count =
(select count(*)
from Table
where CrtDt <= #datecounter and ExpDt > #datecounter)
insert into #datelist values (#datecounter, #count)
set #datecounter = dateadd(dd, #interval, #datecounter)
end
select * from #datelist order by 1
It loops through all the dates in your range, counting valid results for each one.
Check this,
DECLARE #StartDate DATETIME,
#EndDate DATETIME;
SELECT #StartDate = '20110501'
,#EndDate = '20110801';
SELECT
DATEADD(d, x.number, #StartDate) AS MonthName1
,
x.number
FROM master.dbo.spt_values x
WHERE x.type = 'P'
AND x.number <= DATEDIFF(MONTH, #StartDate, #EndDate);
The above query give the list of dates between 2 dates.
As per your table and question, check this also.
declare #table table(id int,frdt datetime, todt datetime)
insert into #table values (1,GETDATE()-20, GETDATE()-19)
,(2,GETDATE()-9, GETDATE()-8)
,(3,GETDATE()+20, GETDATE()+18)
,(4,GETDATE(), GETDATE()-1)
,(5,GETDATE()-20, GETDATE())
,(6,GETDATE()-10, GETDATE()+10 )
select * from #table
declare #frdt datetime = null , #todt datetime = getdate()-10
select #frdt, #todt,* from #table
where
(#frdt is null or #frdt between frdt and todt)
and
(#todt is null or #todt between frdt and todt)
select #frdt = GETDATE()-15 , #todt = GETDATE()
select #frdt, #todt,* from #table
where
(#frdt is null or #frdt between frdt and todt)
and
(#todt is null or #todt between frdt and todt)

Showing Data for those Dates which are not present in Database Table

I am trying show attendance record for employees in particular Branch, let Say "Pune Branch".
While Showing Weekly Records, It only shows the record of dates for which there is an entry in database table. I also want to show record for those Date on which there is no any employee present.
Suppose In Log_TB there are 2 employee record present for 28 Apr 2015 out of 2 Employees, Then It Shows
And If No records for that Date then it Returns nothing.
I want result Like
Here is my Query
Declare
#Date date = GETDATE(),
#date1 date,
#Total int
set #date1 = (CONVERT(date,DATEADD(DD,-6,#Date),108));
select #Total = Count(User_TB.User_Id)
from User_TB join Branch_TB
on User_TB.User_Branch = Branch_TB.Branch_Name
where User_TB.User_Branch = 'Pune';
select convert(varchar,Log_TB.Date,106) AS Date,
CONVERT(CHAR(3),DATENAME(weekday,Log_TB.Date)) AS Day,
#Total AS Total,COUNT(Log_TB.User_Id) Present,
(#Total-COUNT(Log_TB.User_Id)) AS Absent
From Log_TB join User_TB on Log_TB.User_Id = User_TB.User_Id
where Log_TB.Date <= (CONVERT(date,#Date,108))
and Log_TB.Date >= #date1 and User_TB.User_Branch = 'Pune'
group by Log_TB.Date;
My table definition
CREATE TABLE [dbo].[Log_TB]
(
[User_Id] [varchar](50) NOT NULL,
[First_Login] [time](0) NULL,
[Logout] [time](0) NULL,
[Date] [date] NULL,
[Working_Hrs] [time](0) NULL,
[extra_Int] [int] NOT NULL,
[extra_String] [varchar](50) NULL
)
What you need is a Numbers or a Date table. You can generate it using something like this
DECLARE #date1 DATE = '20150401',#Date DATE= GETDATE();
;WITH CTE AS
(
SELECT #date1 as datecol
UNION ALL SELECT DATEADD(day,1,datecol) FROM CTE WHERE DATEADD(day,1,datecol) <= #Date
)
SELECT * FROM CTE
In your query, you would use it like this
Declare
#Date date = GETDATE(),
#date1 date,
#Total int
set #date1 = (CONVERT(date,DATEADD(DD,-6,#Date),108));
select #Total = Count(User_TB.User_Id)
from User_TB join Branch_TB
on User_TB.User_Branch = Branch_TB.Branch_Name
where User_TB.User_Branch = 'Pune';
DECLARE #date1 DATE = '20150401',#Date DATE= GETDATE();
;WITH CTE AS
(
SELECT #date1 as datecol
UNION ALL SELECT DATEADD(day,1,datecol) FROM CTE WHERE DATEADD(day,1,datecol) <= #Date
)
select convert(varchar,CTE.datecol,106) AS Date,
CONVERT(CHAR(3),DATENAME(weekday,CTE.datecol)) AS Day,
#Total AS Total,COUNT(User_TB.User_Id) Present,
(#Total-COUNT(User_TB.User_Id)) AS Absent
From CTE LEFT JOIN Log_TB ON Log_TB.Log_TB.Date = CTE.datecol
LEFT join User_TB on Log_TB.User_Id = User_TB.User_Id
and User_TB.User_Branch = 'Pune'
group by CTE.datecol;
Declare #date datetime -- its a starting date
Set #Date = '1-Apr-2015'
Declare #table table (date datetime)
-- inserts data from starting date till getdate
while #date <> convert(datetime,convert(varchar(10),getdate(),101),101)
begin
insert into #table
select #date aa
select #date = #date+1
end
select * from #table
Just join #table and your data with left join
Select *
from #table left join (Your data) with condition date.

How can I generate a temporary table filled with dates in SQL Server 2000?

I need to make a temporary table that holds of range of dates, as well as a couple of columns that hold placeholder values (0) for future use. The dates I need are the first day of each month between $startDate and $endDate where these variables can be several years apart.
My original sql statement looked like this:
select dbo.FirstOfMonth(InsertDate) as Month, 0 as Trials, 0 as Sales
into #dates
from customer
group by dbo.FirstOfMonth(InsertDate)
"FirstOfMonth" is a user-defined function I made that pretty much does what it says, returning the first day of the month for the provided date with the time at exactly midnight.
This produced almost exactly what I needed until I discovered there were occasionally gaps in my dates where I had a few months were there were no records insert dates. Since my result must still have the missing months I need a different approach.
I have added the following declarations to the stored procedure anticipating their need for the range of the dates I need ...
declare $startDate set $startDate = select min(InsertDate) from customer
declare $endDate set $endDate = select max(InsertDate) from customer
... but I have no idea what to do from here.
I know this question is similar to this question but, quite frankly, that answer is over my head (I don't often work with SQL and when I do it tends to be on older versions of SQL Server) and there are a few minor differences that are throwing me off.
I needed something similar, but all DAYS instead of all MONTHS.
Using the code from MatBailie as a starting point, here's the SQL for creating a permanent table with all dates from 2000-01-01 to 2099-12-31:
CREATE TABLE _Dates (
d DATE,
PRIMARY KEY (d)
)
DECLARE #dIncr DATE = '2000-01-01'
DECLARE #dEnd DATE = '2100-01-01'
WHILE ( #dIncr < #dEnd )
BEGIN
INSERT INTO _Dates (d) VALUES( #dIncr )
SELECT #dIncr = DATEADD(DAY, 1, #dIncr )
END
This will quickly populate a table with 170 years worth of dates.
CREATE TABLE CalendarMonths (
date DATETIME,
PRIMARY KEY (date)
)
DECLARE
#basedate DATETIME,
#offset INT
SELECT
#basedate = '01 Jan 2000',
#offset = 1
WHILE (#offset < 2048)
BEGIN
INSERT INTO CalendarMonths SELECT DATEADD(MONTH, #offset, date) FROM CalendarMonths
SELECT #offset = #offset + #offset
END
You can then use it by LEFT joining on to that table, for the range of dates you require.
I would probably use a Calendar table. Create a permanent table in your database and fill it with all of the dates. Even if you covered a 100 year range, the table would still only have ~36,525 rows in it.
CREATE TABLE dbo.Calendar (
calendar_date DATETIME NOT NULL,
is_weekend BIT NOT NULL,
is_holiday BIT NOT NULL,
CONSTRAINT PK_Calendar PRIMARY KEY CLUSTERED (calendar_date)
)
Once the table is created, just populate it once in a loop, so that it's always out there and available to you.
Your query then could be something like this:
SELECT
C.calendar_date,
0 AS trials,
0 AS sales
FROM
dbo.Calendar C
WHERE
C.calendar_date BETWEEN #start_date AND #end_date AND
DAY(C.calendar_date) = 1
You can join in the Customers table however you need to, outer joining on FirstOfMonth(InsertDate) = C.calendar_date if that's what you want.
You can also include a column for day_of_month if you want which would avoid the overhead of calling the DAY() function, but that's fairly trivial, so it probably doesn't matter one way or another.
This of course will not work in SQL-Server 2000 but in a modern database where you don't want to create a permanent table. You can use a table variable instead creating a table so you can left join the data try this. Change the DAY to HOUR etc to change the increment type.
declare #CalendarMonths table (date DATETIME, PRIMARY KEY (date)
)
DECLARE
#basedate DATETIME,
#offset INT
SELECT
#basedate = '01 Jan 2014',
#offset = 1
INSERT INTO #CalendarMonths SELECT #basedate
WHILE ( DATEADD(DAY, #offset, #basedate) < CURRENT_TIMESTAMP)
BEGIN
INSERT INTO #CalendarMonths SELECT DATEADD(HOUR, #offset, date) FROM #CalendarMonths where DATEADD(DAY, #offset, date) < CURRENT_TIMESTAMP
SELECT #offset = #offset + #offset
END
A starting point of a useful kludge to specify a range or specific list of dates:
SELECT *
FROM
(SELECT CONVERT(DateTime,'2017-1-1')+number AS [Date]
FROM master..spt_values WHERE type='P' AND number<370) AS DatesList
WHERE DatesList.Date IN ('2017-1-1','2017-4-14','2017-4-17','2017-12-25','2017-12-26')
You can get 0 to 2047 out of master..spt_values WHERE type='P', so that's five and a half year's worth of dates if you need it!
Tested below and it works, though it's a bit convoluted.
I assigned arbitrary values to the dates for the test.
DECLARE #SD smalldatetime,
#ED smalldatetime,
#FD smalldatetime,
#LD smalldatetime,
#Mct int,
#currct int = 0
SET #SD = '1/15/2011'
SET #ED = '2/02/2012'
SET #FD = (DATEADD(dd, -1*(Datepart(dd, #SD)-1), #sd))
SET #LD = (DATEADD(dd, -1*(Datepart(dd, #ED)-1), #ED))
SET #Mct = DATEDIFF(mm, #FD, #LD)
CREATE TABLE #MyTempTable (FoM smalldatetime, Trials int, Sales money)
WHILE #currct <= #Mct
BEGIN
INSERT INTO #MyTempTable (FoM, Trials, Sales)
VALUES
(DATEADD(MM, #currct, #FD), 0, 0)
SET #currct = #currct + 1
END
SELECT * FROM #MyTempTable
DROP TABLE #MyTempTable
For SQL Server 2000, this stackoverflow post looks promising for a way to temporarily generate dates calculated off of a start and end date. It's not exactly the same but quite similar. This post has a very in-depth answer on truncating dates, if needed.
In case anyone stumbles on this question and is working in PostgreSQL instead of SQL Server 2000, here is how you might do it there...
PostgreSQL has a nifty series generating function. For your example, you could use this series of all days instead of generating an entire calendar table, and then do groupings and matchups from there.
SELECT current_date + s.a AS dates FROM generate_series(0,14,7) AS s(a);
dates
------------
2004-02-05
2004-02-12
2004-02-19
(3 rows)
SELECT * FROM generate_series('2008-03-01 00:00'::timestamp,
'2008-03-04 12:00', '10 hours');
generate_series
---------------------
2008-03-01 00:00:00
2008-03-01 10:00:00
2008-03-01 20:00:00
2008-03-02 06:00:00
2008-03-02 16:00:00
2008-03-03 02:00:00
2008-03-03 12:00:00
2008-03-03 22:00:00
2008-03-04 08:00:00
(9 rows)
I would also look into date_trunc from PostgreSQL using 'month' for the truncator field to maybe refactor your original query to easily match with a date_trunc version of the calendar series.
select top (datediff(D,#start,#end)) dateadd(D,id-1,#start)
from BIG_TABLE_WITH_NO_JUMPS_IN_ID
declare #start datetime
set #start = '2016-09-01'
declare #end datetime
set #end = '2016-09-30'
create table #Date
(
table_id int identity(1,1) NOT NULL,
counterDate datetime NULL
);
insert into #Date select top (datediff(D,#start,#end)) NULL from SOME_TABLE
update #Date set counterDate = dateadd(D,table_id - 1, #start)
The code above should populate the table with all the dates between the start and end. You would then just join on this table to get all of the dates needed. If you only needed a certain day of each month, you could dateadd a month instead.
SELECT P.Id
, DATEADD ( DD, -P.Id, P.Date ) AS Date
FROM (SELECT TOP 1000 ROW_NUMBER () OVER (ORDER BY (SELECT NULL)) AS Id, CAST(GETDATE () AS DATE) AS Date FROM master.dbo.spt_values) AS P
This query returns a table calendar for the last 1000 days or so. It can be put in a temporary or other table.
Create a table variable containing a date for each month in a year:
declare #months table (reportMonth date, PRIMARY KEY (reportMonth));
declare #start date = '2018', #month int = 0; -- base 0 month
while (#month < 12)
begin
insert into #months select dateAdd(month, #month, #start);
select #month = #month + 1;
end
--verify
select * from #months;
This is by far the quickest method I have found (much quicker than inserting rows 1 by 1 in a WHILE loop):
DECLARE #startDate DATE = '1900-01-01'
DECLARE #endDate DATE = '2050-01-01'
SELECT DATEADD(DAY, sequenceNumber, #startDate) AS TheDate
INTO #TheDates
FROM (
SELECT ones.n + 10*tens.n + 100*hundreds.n + 1000*thousands.n + 10000*tenthousands.n AS sequenceNumber
FROM
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) ones(n),
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) tens(n),
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) hundreds(n),
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) thousands(n),
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) tenthousands(n)
WHERE ones.n + 10*tens.n + 100*hundreds.n + 1000*thousands.n + 10000*tenthousands.n <= DATEDIFF(day, #startDate, #endDate)
) theNumbers
SELECT *
FROM #TheDates
ORDER BY TheDate
The recursive answer:
DECLARE #startDate AS date = '20220315';
DECLARE #endDate AS date = '20230316'; -- inclusive
WITH cte_minutes(dt)
AS (
SELECT
DATEFROMPARTS(YEAR(#startDate), MONTH(#startDate), 1)
UNION ALL
SELECT
DATEADD(month, 1, dt)
FROM
cte_minutes
WHERE DATEADD(month, 1, dt) < #endDate
)
SELECT
dt
into #dates
FROM
cte_minutes
WHERE
dt >= #startDate
AND
dt <= #endDate
OPTION (MAXRECURSION 2000);
DROP TABLE dbo.#dates