SQL: How to create a temp table and fill it with date within a select-from statement - sql

I wish to create a temp table with 1 datetime column and then fill it with date(30 days before today). I wish to do all these in a select-from statement.
I could do it with a "WITH" loop as below prior to the select-from statement. However, I wish to do it within a select-from statement.
declare #endDate datetime
set #endDate = dateadd(day,-30,getdate())
with CTE_Table (
Select dataDate = dateadd(day,-1,getdate()) from CTE_Table
where datediff(day,dataDate,#endDate) < 0
)
select * from CTE_Table
Please help... :....(

You can use SELECT ... INTO.
BTW Your recursive CTE is invalid. A fixed version is below
DECLARE #endDate DATETIME
SET #endDate = dateadd(day, -30, getdate());
WITH CTE_Table(dataDate)
AS (SELECT dateadd(day, -1, getdate())
UNION ALL
SELECT dateadd(day, -1, dataDate)
FROM CTE_Table
WHERE datediff(day, dataDate, #endDate) < 0)
SELECT dataDate
INTO #T
FROM CTE_Table

You could do:
CREATE TABLE #temptable
(
DateColumn DATETIME
)
INSERT INTO #temptable
SELECT dataDate FROM CTE_Table

Related

How to cast and convert to datetime in where condition in t-sql?

I am trying to get last months worth of data from the table vis_p_activities_final and tried the query below:
SELECT * FROM DPICD.vis_p_activities_final
WHERE DPICD.vis_p_activities_final.current_activity_code IN (
'SDBPR', 'SDBPU', 'XSDBPU', 'SDBPUX' )
AND CAST((DPICD.vis_p_activities_final.raised_date_time) AS DATETIME) >=
Dateadd(month, -1, CURRENT_TIMESTAMP)`
the raised_date_time column is VARCHAR and I want to convert it to datetime for the filter. How can I do that?
you can use temp table as
declare #lastmonth datetime
set #lastmonth = Dateadd(month, -1, CURRENT_TIMESTAMP)`
SELECT *, CAST((DPICD.vis_p_activities_final.raised_date_time) AS DATETIME) as
'revised_date' into #tmp FROM DPICD.vis_p_activities_final
WHERE DPICD.vis_p_activities_final.current_activity_code IN (
'SDBPR', 'SDBPU', 'XSDBPU', 'SDBPUX' )
`
select * from #tmp where revised_date >= #lastmonth

Recursive CTE on Dates

I want to recursively loop though the temporary table by date1 field using following query in Sql server. I want that the #stardate and #enddate should auto increment up to the #stopcriteria initially starting from
'01/01/2011' to 12/31/2011' and then
'01/01/2012' to 12/31/2012' and so on up to #stopCriteria and resultset should keep joining with union. I have written following query using cte but is not working.
CREATE TABLE #tempbbs576 ( id int, amount money, date1 date)
insert into #tempbbs576(id,amount,date1) values(1,1000,'1/1/2018')
insert into #tempbbs576(id,amount,date1) values(2,20010,'22/3/2019')
insert into #tempbbs576(id,amount,date1) values(3,40010,'1/1/2017')
insert into #tempbbs576(id,amount,date1) values(4,50010,'23/4/2018')
insert into #tempbbs576(id,amount,date1) values(5,60010,'1/1/2018')
insert into #tempbbs576(id,amount,date1) values(6,70010,'21/1/2018')
DECLARE #startDate DATE;
DECLARE #endDate DATE;
DECLARE #stopCriteria DATE;
SET #startDate='01/01/2011'; SET #endDate='12/31/2011'; SET #stopCriteria='01/01/2018';
;WITH ctesequence
AS (SELECT 'Year' + Datename(year, Dateadd(year, 1, #startDate)) /*'2012'*/
AS FiscalYear, Count(DISTINCT id) AS Last2Years
FROM [dbo].[#tempbbs576](nolock) WHERE date1 BETWEEN #startDate AND
#endDate AND id IN (SELECT id FROM [dbo].[#tempbbs576]
WHERE date1 < Dateadd(year, -1, #startDate) AND id
NOT IN (SELECT id FROM [dbo].[#tempbbs576] WHERE date1 BETWEEN
Dateadd(year,-1, #startDate) AND Dateadd( year, -1, #endDate ) ))
UNION
SELECT 'Year' + Datename(year, Dateadd(year, 1, #startDate)) /*'2012'*/
AS FiscalYear, Count(DISTINCT id) AS Last2Years FROM ctesequence WHERE date1 <= #stopCriteria)
SELECT * FROM ctesequence OPTION(maxrecursion 0)
Please let me know if it is possible through cte.
Thanks in Advance,
Amar

Add a record for every Week-Day of the year to a blank table

I have a blank table that has two columns [ID] and [MyDate].
I would like to populate that table with all of the days of the current year MINUS weekends.
Is there a way to do this with a SQL query?
In this case I am using MSSQL T-SQL
I do not have any example code, as I am at a loss on where to get started for this scenario.
Using a numbers (Tally) table helps you to avoid using loops.
If you don't already have a numbers table, you can use this script to create it:
SELECT TOP 10000 IDENTITY(int,0,1) AS Number
INTO Tally
FROM sys.objects s1
CROSS JOIN sys.objects s2
ALTER TABLE Tally ADD CONSTRAINT PK_NumbersTest PRIMARY KEY CLUSTERED (Number)
For more information about the creation of a numbers table, read this SO post.
Now that you have a numbers table, you can use a cte to generate the dates you want. I've used DATEFROMPARTS and GETDATE() to get Jauary 1st of the current year, if you are using a version of sql server below 2012 you need to use other methods for that:
DECLARE #StartDate Date,
#EndDate Date
SELECT #StartDate = DATEFROMPARTS(YEAR(GetDate()), 1, 1)
SELECT #EndDate = DATEADD(Year, 1, #StartDate)
Now, create a CTE to get the dates required using the numbers table, and insert the records from the cte to the table:
;WITH CTE AS
(
SELECT DATEADD(Day, Number, #StartDate) As TheDate
FROM Tally
WHERE DATEADD(Day, Number, #StartDate) < #EndDate
)
INSERT INTO WeekDays
SELECT TheDate
FROM CTE
WHERE DATEPART(WeekDay, TheDate) BETWEEN 2 AND 6
See a live demo on rextester.
This will do it. Here the 1 and the 7 represents Sunday and Saturday
CREATE TABLE T (
ID INT NOT NULL IDENTITY(1,1),
MyDate DATE NOT NULL)
DECLARE #Start DATE
DECLARE #End DATE
SET #Start = '20170101'
SET #End = '20171231'
WHILE #Start <= #End
BEGIN
IF (DATEPART(DW, #Start) NOT IN (1,7))
BEGIN
INSERT INTO T (MyDate) VALUES (#Start)
END
SET #Start = DATEADD(DAY, 1, #Start)
END
SELECT * FROM T
Here's my quick attempt at your problem. Just use your table instead
select
CAST('2017-03-15' as datetime) as datestuff
into #test
Delete from #test
DECLARE #Y datetime = CAST('2017-12-31' AS DATE)
while #y != '2017-01-01'
begin
if DATENAME(DW, #y) not IN ('SUNDAY', 'SATURDAY')
BEGIN
INSERT INTO #test
SELECT #y
END
SET #Y = DATEADD(DD, -1, #Y)
end
select * from #test

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

generate sql temp table of sequential dates to left outer join to

i have a table of data that i want to select out via stored proc such that users can connect a MS excel front end to it and use the raw data as a source to graph.
The problem with the raw data of the table is there exist gaps in the dates because if there is no data for a given day (there is no records with that date) then when users try to graph it it creates problems.
I want too update my stored proc to left outer join to a temp table of dates so that the right side will come in as nulls that i can cast to zero's for them to have a simple plotting experience.
how do i best generate a one field table of dates between a start and end date?
In SQL Server 2005 and up, you can use something like this (a Common Table Expression CTE) to do this:
DECLARE #DateFrom DATETIME
SET #DateFrom = '2011-01-01'
DECLARE #DateTo DATETIME
SET #DateTo = '2011-01-10'
;WITH DateRanges AS
(
SELECT #DateFrom AS 'DateValue'
UNION ALL
SELECT DATEADD(DAY, 1, DateValue)
FROM DateRanges
WHERE DateValue < #DateTo
)
SELECT * FROM DateRanges
You could LEFT OUTER JOIN this CTE against your table and return the result.
Another way to do it is with a memory table. It won't choke due to recursion limitations like some of the above solutions.
DECLARE #dates AS TABLE ([Date] date);
DECLARE #date date = {d '2010-10-01'};
DECLARE #endDate date = {d '2010-11-01'};
while (#date < #endDate)
BEGIN
INSERT INTO #dates VALUES (#date);
SET #date = dateadd(DAY, 1, #date)
END
SELECT * FROM #dates;
SQL Fiddle
One way would be with a CTE:
with cte_dates as (
select cast('20110119' as datetime) as [date]
union all
select dateadd(dd, 1, [date])
from cte_dates
where dateadd(dd, 1, [date]) <= '20111231'
)
select [date], YourColumn
from cte_dates
left join YourTable
on ...
option (maxrecursion 0);