I want to create table or view from a recursion used to generate a date in ssms - sql

I wrote a recursive query to generate a column pf dates. I want the dates to be stored as a table in a db but can't seem to find a way.
declare #startdate date = '2014-01-01';
declare #enddate date = '2023-12-31';
with calendar as
(
select #startdate as [orderDate]
union all
select DATEADD(dd,1,[orderdate])
from calendar
where DATEADD(dd,1,[orderdate])<= #enddate
)
select * from calendar
option (maxrecursion 0);

you can try this one to fill a new table your_table with the dates.
You can use that as a basis for your further operations.
WITH x AS (SELECT n FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) v(n))
select
convert(date, dat ) Dat
into your_table
from
(
SELECT top 100 percent
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) Line,
dateadd(day, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)), '2014-01-01') Dat
FROM x ones, x tens, x hundreds, x thousands
ORDER BY 1
) basis
where dat <= '2023-12-31'

Related

SQL temp date table generation

I wonder is there a way to generate a temp table containing dates but using between, because I have to use such a construction.
between Convert(datetime, '2022-01-01T00:00:00.000', 126) and Convert(datetime, '2022-03-04T23:59:59.998', 126)
I mean it should use between not StartDate,EndDate.
Another option which I think performs better than a recursive CTE
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT 0 AS I
UNION ALL
SELECT TOP (DATEDIFF(DAY, '20220101', '20220304'))
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
FROM N N1, N N2, N N3),
Dates AS(
SELECT DATEADD(DAY, T.I, '20220101') AS Date
FROM Tally T)
SELECT D.Date
into #tmpDates
FROM Dates D
EDIT
I always have a calendar table in my database, so I can just join on that. This performs quite well and the queries are much easier
An option for a getting the temp table. Not 100% it will do what's required. Hope this helps though.
DECLARE #start_date date = '2022-01-01',
#end_date date = '2022-03-04'
;WITH cte AS (
SELECT #start_date as DateRet
UNION ALL
SELECT CAST(DATEADD(day,1,dateRet) as date)
FROM cte
WHERE dateret < #end_date
)
SELECT *
into #tmpDates
FROM cte

SQL - create multiple calendars in one table

I am trying to create a table which calculates multiple calendars depending on the start and end date of a certain row. I have a table which looks like this:
key Start_date End_date
123.1 1-10-2009 24-12-2009
123.2 1-7-2010 9-2-2011
123.3 1-5-2011 30-10-2011
.........
For each key I want a new row with startdate +1 month until enddate.
For now I have query which works only if my temporary table contains one row, which is:
DECLARE #StartDate DATE = (select Start_date from #dim2);
SET DATEFIRST 7;
SET DATEFORMAT ymd;
SET LANGUAGE US_ENGLISH;
DECLARE #CutoffDate DATE = (select End_date from #dim2);
CREATE TABLE #dim3
([verwachte_aflossing] DATE,-- PRIMARY KEY,
);
INSERT #dim3([verwachte_aflossing] )
SELECT d
FROM
(
SELECT d = DATEADD(month, rn-1, #StartDate)
FROM
(
SELECT TOP (DATEDIFF(month, #StartDate, #CutoffDate))
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
Does anyone now how to handle this?
For SQL Server recursive cte is one option to do that
WITH CTE as
(
select [Key], start_date, end_date from table
union all
select [Key], dateadd(month,1,start_date) start_date, end_date
from cte
where datediff(month, start_date, end_date) > 0
)
SELECT * FROM CTE
OPTION (MAXRECURSION 0)

Find missing date as compare to calendar

I am explain problem in short.
select distinct DATE from #Table where DATE >='2016-01-01'
Output :
Date
2016-11-23
2016-11-22
2016-11-21
2016-11-19
2016-11-18
Now i need to find out missing date a compare to our calender dates from year '2016'
i.e. Here date '2016-11-20' is missing.
I want list of missing dates.
Thanks for reading this. Have nice day.
You need to generate dates and you have to find missing ones. Below with recursive cte i have done it
;WITH CTE AS
(
SELECT CONVERT(DATE,'2016-01-01') AS DATE1
UNION ALL
SELECT DATEADD(DD,1,DATE1) FROM CTE WHERE DATE1<'2016-12-31'
)
SELECT DATE1 MISSING_ONE FROM CTE
EXCEPT
SELECT * FROM #TABLE1
option(maxrecursion 0)
Using CTE and get all dates in CTE table then compare with your table.
CREATE TABLE #yourTable(_Values DATE)
INSERT INTO #yourTable(_Values)
SELECT '2016-11-23' UNION ALL
SELECT '2016-11-22' UNION ALL
SELECT '2016-11-21' UNION ALL
SELECT '2016-11-19' UNION ALL
SELECT '2016-11-18'
DECLARE #DATE DATE = '2016-11-01'
;WITH CTEYear (_Date) AS
(
SELECT #DATE
UNION ALL
SELECT DATEADD(DAY,1,_Date)
FROM CTEYear
WHERE _Date < EOMONTH(#DATE,0)
)
SELECT * FROM CTEYear
WHERE NOT EXISTS(SELECT 1 FROM #yourTable WHERE _Date = _Values)
OPTION(maxrecursion 0)
You need to generate the dates and then find the missing ones. A recursive CTE is one way to generate a handful of dates. Another way is to use master..spt_values as a list of numbers:
with n as (
select row_number() over (order by (select null)) - 1 as n
from master..spt_values
),
d as (
select dateadd(day, n.n, cast('2016-01-01' as date)) as dte
from n
where n <= 365
)
select d.date
from d left join
#table t
on d.dte = t.date
where t.date is null;
If you are happy enough with ranges of missing dates, you don't need a list of dates at all:
select date, (datediff(day, date, next_date) - 1) as num_missing
from (select t.*, lead(t.date) over (order by t.date) as next_date
from #table t
where t.date >= '2016-01-01'
) t
where next_date <> dateadd(day, 1, date);

How can I sum values per day and then plot them on calendar from start date to last date

I have a table, part of which is given below. It contain multiple values (durations) per day. I need two things 1) addition of durations per day. 2) plotting them on calendar in such a way that startdate is first_date from the table and last_date is Last_update from the table. I want to mention 0 for which date there is no duration. I think it will something like below but need help.
;WITH AllDates AS(
SELECT #Fromdate As TheDate
UNION ALL
SELECT TheDate + 1
FROM AllDates
WHERE TheDate + 1 <= #ToDate
)SELECT UserId,
TheDate,
COALESCE(
SUM(
-- When the game starts and ends in the same date
CASE WHEN DATEDIFF(DAY, GameStartTime, GameEndTime) = 0
Here is what I am looking for
Another way to generate the date range you are after would be something like .....
;WITH DateLimits AS
(
SELECT MIN(First_Date) FirstDate
,MAX(Last_Update) LastDate
FROM TableName
),
DateRange AS
(
SELECT TOP (SELECT DATEDIFF(DAY,FirstDate,LastDate ) FROM DateLimits)
DATEADD(DAY
,ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
, (SELECT FirstDate FROM DateLimits)
) AS Dates
FROM master..spt_values a cross join master..spt_values b
)
SELECT * FROM DateRange --<-- you have the desired date range here
-- other query whatever you need.

Sql to select row from each day of a month

I have a table which store records of all dates of a month. I want to retrieve some data from it. The table is so large that I should only selecting a fews of them. If the records have a column "ric_date" which is a date, how can I select records from each of the dates in a month, while selecting only a fews from each date?
The table is so large that the records for 1 date can have 100000 records.
WITH T AS (
SELECT ric_date
FROM yourTable
WHERE rice_date BETWEEN #start_date AND #end_date -- thanks Aaron Bertrand
GROUP BY ric_date
)
SELECT CA.*
FROM T
CROSS APPLY (
SELECT TOP 500 * -- 'a fews'
FROM yourTable AS YT
WHERE YT.ric_date = T.ric_date
ORDER BY someAttribute -- not required, but useful
) AS CA
Rough idea. This will get the first three rows per day for the current month (or as many that exist for any given day - there may be days with no rows represented).
DECLARE
#manys INT = 3,
#month DATE = DATEADD(DAY, 1-DAY(GETDATE()), DATEDIFF(DAY, 0, GETDATE()));
;WITH x AS
(
SELECT some_column, ric_date, rn = ROW_NUMBER() OVER
(PARTITION BY ric_date ORDER BY ric_date)
FROM dbo.data
WHERE ric_date >= #month
AND ric_date < DATEADD(MONTH, 1, #month)
)
SELECT some_column, ric_date FROM x
WHERE rn <= #manys;
If you don't have supporting indexes (most importantly on ric_date), this won't necessarily scale well at the high end.