How to create Temp table with SELECT * INTO tempTable FROM CTE Query - sql

I have a MS SQL CTE query from which I want to create a temporary table. I am not sure how to do it as it gives an Invalid Object name error.
Below is the whole query for reference
SELECT * INTO TEMPBLOCKEDDATES FROM
;with Calendar as (
select EventID, EventTitle, EventStartDate, EventEndDate, EventEnumDays,EventStartTime,EventEndTime, EventRecurring, EventStartDate as PlannedDate
,EventType from EventCalender
where EventActive = 1 AND LanguageID =1 AND EventBlockDate = 1
union all
select EventID, EventTitle, EventStartDate, EventEndDate, EventEnumDays,EventStartTime,EventEndTime, EventRecurring, dateadd(dd, 1, PlannedDate)
,EventType from Calendar
where EventRecurring = 1
and dateadd(dd, 1, PlannedDate) <= EventEndDate
)
select EventID, EventStartDate, EventEndDate, PlannedDate as [EventDates], Cast(PlannedDate As datetime) AS DT, Cast(EventStartTime As time) AS ST,Cast(EventEndTime As time) AS ET, EventTitle
,EventType from Calendar
where (PlannedDate >= GETDATE()) AND ',' + EventEnumDays + ',' like '%,' + cast(datepart(dw, PlannedDate) as char(1)) + ',%'
or EventEnumDays is null
order by EventID, PlannedDate
option (maxrecursion 0)
I would appreciate a point in the right direction or if I can create a temporary table from this CTE query

Sample DDL
create table #Temp
(
EventID int,
EventTitle Varchar(50),
EventStartDate DateTime,
EventEndDate DatetIme,
EventEnumDays int,
EventStartTime Datetime,
EventEndTime DateTime,
EventRecurring Bit,
EventType int
)
;WITH Calendar
AS (SELECT /*...*/)
Insert Into #Temp
Select EventID, EventStartDate, EventEndDate, PlannedDate as [EventDates], Cast(PlannedDate As datetime) AS DT, Cast(EventStartTime As time) AS ST,Cast(EventEndTime As time) AS ET, EventTitle
,EventType from Calendar
where (PlannedDate >= GETDATE()) AND ',' + EventEnumDays + ',' like '%,' + cast(datepart(dw, PlannedDate) as char(1)) + ',%'
or EventEnumDays is null
Make sure that the table is deleted after use
If(OBJECT_ID('tempdb..#temp') Is Not Null)
Begin
Drop Table #Temp
End

Really the format can be quite simple - sometimes there's no need to predefine a temp table - it will be created from results of the select.
Select FieldA...FieldN
into #MyTempTable
from MyTable
So unless you want different types or are very strict on definition, keep things simple. Note also that any temporary table created inside a stored procedure is automatically dropped when the stored procedure finishes executing. If stored procedure A creates a temp table and calls stored procedure B, then B will be able to use the temporary table that A created.
However, it's generally considered good coding practice to explicitly drop every temporary table you create anyway.

How to Use TempTable in Stored Procedure?
Here are the steps:
CREATE TEMP TABLE
-- CREATE TEMP TABLE
Create Table #MyTempTable (
EmployeeID int
);
INSERT TEMP SELECT DATA INTO TEMP TABLE
-- INSERT COMMON DATA
Insert Into #MyTempTable
Select EmployeeID from [EmployeeMaster] Where EmployeeID between 1 and 100
SELECT TEMP TABLE (You can now use this select query)
Select EmployeeID from #MyTempTable
FINAL STEP DROP THE TABLE
Drop Table #MyTempTable
I hope this will help. Simple and Clear :)

The SELECT ... INTO needs to be in the select from the CTE.
;WITH Calendar
AS (SELECT /*... Rest of CTE definition removed for clarity*/)
SELECT EventID,
EventStartDate,
EventEndDate,
PlannedDate AS [EventDates],
Cast(PlannedDate AS DATETIME) AS DT,
Cast(EventStartTime AS TIME) AS ST,
Cast(EventEndTime AS TIME) AS ET,
EventTitle,
EventType
INTO TEMPBLOCKEDDATES /* <---- INTO goes here*/
FROM Calendar
WHERE ( PlannedDate >= Getdate() )
AND ',' + EventEnumDays + ',' LIKE '%,' + Cast(Datepart(dw, PlannedDate) AS CHAR(1)) + ',%'
OR EventEnumDays IS NULL
ORDER BY EventID,
PlannedDate
OPTION (maxrecursion 0)

Here's one slight alteration to the answers of a query that creates the table upon execution (i.e. you don't have to create the table first):
SELECT * INTO #Temp
FROM (
select OptionNo, OptionName from Options where OptionActive = 1
) as X

Select Eventname,
count(Eventname) as 'Counts'
INTO #TEMPTABLE
FROM tblevent
where Eventname like 'A%'
Group by Eventname
order by count(Eventname)
Here by using the into clause the table is directly created

You should also be aware that there are GLOBAL temporary tables. These can be referenced from another connection. They behave pretty much as described by early answers. To create one, simply prefix the table name with ##. That's what I was looking for; hope others that land here find that useful too.

You can also use View to create a temporary/virtual table
CREATE VIEW view_name AS
SELECT column1, column2, ...
FROM table_name
WHERE condition;

Related

Loop through Multiple Database table and Insert into Temp table

Edit for better clarification.
I have a table created with two columns around 60 rows
----SiteDboTable---
SELECT
[SiteName]
, CASE WHEN [Type] = 'Wind' THEN CONCAT('[YYY].[dbo].', '[', Replace(Translate([SiteName], ' -\','???'),'?',''), 'Turbine]')
ELSE CONCAT('[YYY].[dbo].', '[', Replace(Translate([SiteName], ' -\','???'),'?',''), 'Inverter]')
END AS dboName
FROM [XXX].[dbo].[Site]
Order By SiteName
Table output:
SiteName dboName
site1 [YYY].[dbo].[site1Inverter]
.... .....
.... .....
site4 [YYY].[dbo].[site4Inverter]
..n.. ..n..
I want to loop through each row of SiteDboTable and insert each rows data into HLEEtmp_table
Using SiteDboTabletable above, I want to use the two columns (SiteName, dboName) each as a variable. Each variable will be updated/changed in the script below. So that when I run HLEEtmp_table it is changing the SiteName and FROM statement each time. Then the data from each iteration of ``HLEEtmp_table``` iteration, this data will be inputted into another table to store all the data.
---HLEEtmp_table---
'SELECT
dateadd(hour, datediff(hour, 0, DataTimeStamp), 0) AS DataTimeStamp
,'+#SiteName+' AS Site
, DeviceID
, AVG([RealPowerAC]) AS RealPowerAC_MEAN
FROM'+#TableName+' WHERE DataTimeStamp >= DATEADD(day,-30,GETDATE())
GROUP BY dateadd(hour, datediff(hour, 0, DataTimeStamp), 0)
, datepart(hour,DataTimeStamp)
, [DeviceID];'
Below is what I was trying. Not sure if this is the correct approach. A cursor approach might not work, I think.
Any Ideas or help would be appreciated.
First, I am creating my two temp tables needed for my data table to INSERT into and my table containing my FROM statement schemas.
IF (OBJECT_ID('tempdb..#HLEEtmp_table') IS NOT NULL )
DROP TABLE #HLEEtmp_table;
IF (OBJECT_ID('tempdb..#SiteDboTable') IS NOT NULL )
DROP TABLE #SiteDboTable;
IF (OBJECT_ID('tempdb..#HLEEtmp_table2') IS NOT NULL )
DROP TABLE #HLEEtmp_table2;
--Create Temp Table #HLEEtmp_table; this table will hold the data I need---------
CREATE TABLE #HLEEtmp_table (
DataTimeStamp VARCHAR(50),
Site VARCHAR(50),
DeviceID VARCHAR(50),
RealPowerAC_MEAN VARCHAR(50)
)
----------------------------------------------------------
/*Create Temp Table #SiteDboTable:
- This table will list of all [DB].[dbo].[table] names in column [AssetName]
- #SiteDboTable will create a table with 60 rows and 2 columns.
- From #SiteDboTable: need [Site] column and [dboName] column for insert into #HLEEtmp_table
- #SiteDboTable.[Site] = #HLEEtmp_table.[Site]
- #SiteDboTable.[dboName] will be #HLEEtmp_table FROM statement: FROM #SiteDboTable.[dboName] "i.e. [XXX].[dbo].[AVInverter]"*/
SELECT
[SiteName]
, CASE WHEN [Type] = 'Wind' THEN CONCAT('[XXX].[dbo].', '[', Replace(Translate([SiteName], ' -\','???'),'?',''), 'Turbine]')
ELSE CONCAT('[XXX].[dbo].', '[', Replace(Translate([SiteName], ' -\','???'),'?',''), 'Inverter]')
END AS dboName
INTO #SiteDboTable
FROM [YYY].[dbo].[Site]
Order By SiteName
With the data from Temp Table #SiteDboTable, I want to use #SiteDboTable columns in the below table #HLEEtmp_table2. Pull my data from #HLEEtmp_table2 and INSERT into my temp data table #HLEEtmp_table.
---------------------------------
--INSERT INTO #HLEEtmp_table VALUES ('DataTimeStamp','Site','DeviceID','RealPowerAC_MEAN')
DECLARE #TableCount int
DECLARE #SiteName varchar(50)
DECLARE #SQL varchar(max)
DECLARE #TableName varchar(256)
SELECT #TableCount = COUNT(1) from #SiteDboTable
WHILE #TableCount > 0
BEGIN
SELECT TOP 1 #SiteName = SiteName from #SiteDboTable ORDER BY SiteName
SELECT #SQL = '
SELECT
dateadd(hour, datediff(hour, 0, DataTimeStamp), 0) AS DataTimeStamp
,'+#SiteName+' AS Site
, DeviceID
, AVG([RealPowerAC]) AS RealPowerAC_MEAN
INTO #HLEEtmp_table2
FROM
'+#TableName+'
WHERE
DataTimeStamp >= DATEADD(day,-30,GETDATE())
GROUP BY
dateadd(hour, datediff(hour, 0, DataTimeStamp), 0)
, datepart(hour,DataTimeStamp)
, [DeviceID];
-- Drop the Primary Key Column from the temp table
-- Alter Table #HLEEtmp_table2 Drop Column [PrimaryKeyColumn]
-- Insert that into your other big table
Insert Into #HLEEtmp_table
Select * From #HLEEtmp_table2
-- Drop the temp table you created
Drop Table #HLEEtmp_table2
'
EXEC (#SQL)
DELETE #SiteDboTable WHERE dboName = #TableName
SELECT #SiteName = COUNT(1) from #SiteDboTable
END
if I where I could have added
Print (#SQL)
EXEC (#SQL)
and that should give me the dynamic SQL which you are executing and that way it will be easy to troubleshoot .
HTH

How to ORDER BY and INSERT to TABLE when loading data from JSON

I need help to load data from JSON to a table but have them ordered/sorted and insert to table?
DECLARE #IN_DATESJSON NVARCHAR(MAX) = N'[{"CreatedDate":"2018-10-10T09:07:29Z"},{"CreatedDate":"2018-10-09T09:07:29Z"},{"CreatedDate":"2018-10-08T07:07:08Z"}]';
DECLARE #V_CALLSTBL AS TABLE (CreatedDate DATETIME);
IF (ISJSON(#IN_DATESJSON) = 1)
BEGIN
INSERT INTO #V_CALLSTBL
SELECT *
FROM OPENJSON (#IN_DATESJSON)
WITH (CreatedDate DATETIME2)
-- ORDER BY CreatedDate ASC -- THIS DOESN'T WORK*
END
SELECT * FROM #V_CALLSTBL;
CreatedDate
-----------------------
2018-10-10 09:07:29.000
2018-10-09 09:07:29.000
2018-10-08 07:07:08.000
Actually, it inserts ordered but you should also select it with order by. Because select not guaranteed to return sorted data as inserted.
SELECT * FROM #V_CALLSTBL ORDER BY CreatedDate ASC;
and you can add an identity column to the table for seeing this.
DECLARE #IN_DATESJSON NVARCHAR(MAX) = N'[{"CreatedDate":"2018-10-10T09:07:29Z"},{"CreatedDate":"2018-10-09T09:07:29Z"},{"CreatedDate":"2018-10-08T07:07:08Z"}]';
DECLARE #V_CALLSTBL AS TABLE (ID INT IDENTITY(1,1), CreatedDate DATETIME);
IF (ISJSON(#IN_DATESJSON) = 1)
BEGIN
INSERT INTO #V_CALLSTBL
SELECT *
FROM OPENJSON (#IN_DATESJSON)
WITH (CreatedDate DATETIME2)
ORDER BY CreatedDate ASC -- THIS DOESN'T WORK*
END
SELECT * FROM #V_CALLSTBL ORDER BY CreatedDate ASC;
If you don't specify an ORDER BY clause in your SELECT statement, it is not guaranteed that the returned data set will be in sorted.
Additionally, to keep a specific table data ordered, you should specify a cluster index on that table column. This will be used for fetching the data faster when a search is made on that column is in the filter criteria.
Again there is no sorting guaranteed if you don't use an ORDER BY clause

T-SQL Pivot Row to Column

I am using SQL Server 2012 and have a table that has the following columns:
ID, Date, CustomFieldName, CustomFieldValue
The CustomFieldName column has 100 values (I know how stupid this sounds) but for the sake of simplicity lets say they are CustomField1, CustomField2, CustomField3
I would like to create a pivot where the out put looks like
ID, Date, CustomField1, CustomField2, CustomField3 where the Max date of CustomFieldVaue's is aggregated.
I have failed horribly in this, but have some progress (though my max isnt right and getting a lot of wrong data)
Any help would be appreciated!
SELECT [date],[id], [CustomField1], [CustomField2], [CustomField3]
from
(
SELECT [date], [id], [CustomFieldValue], [CustomFieldName],
row_number() over(partition by [CustomFieldName] order by [CustomFieldValue]) rn
from CustomTable
) as st
pivot
(
max([CustomFieldValue])
FOR [CustomFieldName] in ([CustomField1], CustomField2, [CustomField3])
) as pivottable
order by [id]
Hope I got it right, you want to pivot the rows (COlumnName1,2,...etc) as columns, so I've made a little script that's ready to run.
I recommend CTE's when it comes to pivoting, makes it easier, if you want to see the whole structure of the query just do a select #xSqlString
set nocount on;
create table
#testTable
(
ID int identity(1,1),
[Date] datetime default getdate(),
CustomFieldName nvarchar(50),
CustomFieldValue date
);
declare
#i int = 0,
#xSqlStringPivot nvarchar(max) = '',
#xSqlString nvarchar(max) = '';
while(#i<=100)
begin
set
#xSqlStringPivot += concat('CustomFieldName',cast(#i as nvarchar(50)),char(13), case when #i<100 then ', ' else '' end);
insert into #testTable
(
CustomFieldName,
CustomFieldValue
)
values
(
concat('CustomFieldName', cast(#i as nvarchar(50))),
dateAdd(day,-#i,getdate())
);
set
#i += 1;
end;
select * from
#testTable
set
#xSqlString =
(
'with ctePiv as
(
select
t.CustomFieldName,
t.CustomFieldValue
from
#testTable t
)
select
*
from
ctePiv
pivot
(
max(customFieldValue) for customFieldName in
(
'+ #xSqlStringPivot +'
)
)p'
);
exec sp_executeSQL #xSqlString
drop table #testTable;
Edit 1
I am referencing the custom table on the while block, basically I'm iterating 100 times to populate the table with 100 rows. This is just to simulate your case.
while(#i<=100)
begin
set
#xSqlStringPivot += concat('CustomFieldName',cast(#i as nvarchar(50)),char(13), case when #i<100 then ', ' else '' end);
insert into #testTable
(
CustomFieldName,
CustomFieldValue
)
values
(
concat('CustomFieldName', cast(#i as nvarchar(50))),
dateAdd(day,-#i,getdate())
);
set
#i += 1;
end;
#xSqlStringPivot is just a small trick to make a list of elements (CustomFieldName0, CustomFieldName1, etc) and to concatenate it to a dynamic SQL string, notice that I'm doing this in the while block, I just concatenate 'CustomField' with the current iteration number and with a carry feed (space).

SQL Query - gather data based on date range - possible variable number of columns

please forgive my inexperience, I hope this isn't too dumb of a question, I'm stuck and have no where else to turn. I'll keep it to the point:
I'm trying to gather payroll data with the results like so:
The issue I have is the variable number of columns. I will be given a date range and are required to return an attendance record for each day in the given range, or a null value if no data is present. I'm using WebAPI as middle tier so I have the ability to perform further data manipulation to achieve this result.
My tables are as follows:
I can't be the first person who needs this done, any articles/posts or anything that would help me accomplish this? Even pseudo code would help; anything!
Thanks a million in advnace!
This is what I've been able to come up with but I'm not even sure if its doable:
-- convert date range into days of month
-- to ensure null values are included in data??
DECLARE #intFlag INT = 0;
DECLARE #numberOfDays INT = DATEDIFF(DAY, #startDate, #endDate);
DECLARE #TMP TABLE (DaysOfMonth date)
WHILE (#intFlag <= #numberOfDays)
BEGIN
INSERT INTO #TMP VALUES (DATEADD(DAY, #intFlag, #startDate));
SET #intFlag = #intFlag + 1
END
-- select days in given data range so c# app can build header row
-- would it help if I pivot this data?
SELECT
DaysOfMonth
FROM
#TMP
ORDER BY
DaysOfMonth
-- get a count for number of people
DECLARE #count INT = 0;
DECLARE #TMPPPL TABLE (Id int identity(1,0), PId Int)
INSERT INTO
#TMPPPL
SELECT
p.PersonId
FROM
dbo.People p
JOIN
dbo.UserTypes ut on p.UserType_UserTypeId = ut.UserTypeId and (ut.Code = 'caregiver' or ut.Code = 'director')
DECLARE #numberOfPeople INT = (SELECT COUNT(1) FROM #TMPPPL)
-- create and execute sproc to return row of data for each person
WHILE (#count <= #numberOfPeople)
BEGIN
-- STUCK HERE, This obviously won't work but what else can I do?
EXEC GetPersonAttendanceHours #personId, #startDate, #endDate;
SET #count = #count + 1
END
This was interesting. I think this will do what you're looking for. First test data:
CREATE TABLE people (PersonID int, Name varchar(30))
INSERT INTO people (PersonID, Name)
SELECT 1, 'Kelly'
UNION ALL SELECT 2, 'Dave'
UNION ALL SELECT 3, 'Mike'
CREATE TABLE attendances (PersonID int, SignIn datetime, SignOut datetime)
INSERT INTO attendances (PersonID, SignIn, SignOut)
SELECT 1, '1-Feb-2015 08:00', '1-Feb-2015 09:00'
UNION ALL SELECT 1, '1-Feb-2015 12:00', '1-Feb-2015 12:30'
UNION ALL SELECT 2, '2-Feb-2015 08:00', '2-Feb-2015 08:15'
UNION ALL SELECT 1, '3-Feb-2015 08:00', '3-Feb-2015 09:00'
UNION ALL SELECT 1, '4-Feb-2015 08:00', '4-Feb-2015 08:30'
UNION ALL SELECT 2, '4-Feb-2015 08:00', '4-Feb-2015 10:00'
UNION ALL SELECT 2, '6-Feb-2015 12:00', '6-Feb-2015 15:00'
UNION ALL SELECT 3, '6-Feb-2015 15:00', '6-Feb-2015 17:00'
UNION ALL SELECT 3, '8-Feb-2015 10:00', '8-Feb-2015 12:00'
Then a dynamic query:
DECLARE #startDate DATETIME='1-Feb-2015'
DECLARE #endDate DATETIME='9-Feb-2015'
DECLARE #numberOfDays INT = DATEDIFF(DAY, #startDate, #endDate)
declare #dayColumns TABLE (delta int, colName varchar(12))
-- Produce 1 row for each day in the report. Note that this is limited by the
-- number of objects in sysobjects (which is about 2000 so it's a high limit)
-- Each row contains a delta date offset, #startDate+delta gives each date to report
-- which is converted to a valid SQL column name in the format colYYYYMMDD
INSERT INTO #dayColumns (delta, colName)
SELECT delta, 'col'+CONVERT(varchar(12),DATEADD(day,delta,#startDate),112) as colName from (
select (ROW_NUMBER() OVER (ORDER BY sysobjects.id))-1 as delta FROM sysobjects
) daysAhead
WHERE delta<=#numberOfDays
-- Create a comma seperated list of columns to report
DECLARE #cols AS NVARCHAR(MAX)= ''
SELECT #cols=CASE WHEN #cols='' THEN #cols ELSE #cols+',' END + colName FROM #dayColumns ORDER BY delta
DECLARE #totalHours AS NVARCHAR(MAX)= ''
SELECT #totalHours=CASE WHEN #totalHours='' THEN '' ELSE #totalHours+' + ' END + 'ISNULL(' + colName +',0)' FROM #dayColumns ORDER BY delta
-- Produce a SQL statement which outputs a variable number of pivoted columns
DECLARE #query AS NVARCHAR(MAX)
SELECT #query=
'declare #days TABLE (reportDay date, colName varchar(12))
INSERT INTO #days (reportDay, colName)
SELECT DATEADD(day,Delta,'''+CONVERT(varchar(22),#startDate,121)+'''), ''col''+CONVERT(varchar(12),DATEADD(day,delta,'''+CONVERT(varchar(22),#startDate,121)+'''),112) as colName from (
select (ROW_NUMBER() OVER (ORDER BY sysobjects.id))-1 as Delta FROM sysobjects
) daysAhead
WHERE Delta<='+CAST(#numberOfDays as varchar(10))+'
SELECT p.Name, pivotedAttendance.*,'+#totalHours+' as totalHours FROM (
SELECT * FROM (
select p.PersonID, d.colName, CAST(DATEDIFF(MINUTE, a.SignIn, a.SignOut)/60.0 as decimal(5,1)) as hrsAttendance
from #days d
CROSS JOIN people p
LEFT OUTER JOIN attendances a ON a.PersonID=p.PersonID AND CAST(a.SignOut as DATE)=d.reportDay
) as s
PIVOT (
SUM(hrsAttendance) FOR colName in ('+#cols+')
) as pa
) as pivotedAttendance
INNER JOIN people p on p.PersonID=pivotedAttendance.PersonID'
-- Run the query
EXEC (#query)
Which produces data in a similar format to your example, with all of the days in the report range and a row for each person. From the above I see:
For presentation purposes you should be able to convert the column name to a display-able date (just parse the YYYYMMDD out of the column name). The date can't be used as the column name directly as it produces an invalid column name.
SQL Fiddle example here.
This is a variation on a theme that I've done in order to display schedules or attendance. I expect something similar should work with your report. Here is the beginning of your stored procedure:
DECLARE #iDay INT = 0;
DECLARE #countDays INT = DATEDIFF(DAY, #startDate, #endDate);
DECLARE #tempDates TABLE ([tempDate] DATE);
DECLARE #filterDates NVARCHAR;
WHILE (#iDay <= #countDays)
BEGIN
INSERT INTO #tempDates VALUES (DATEADD(DAY, #iDay, #startDate));
SET #iDay = #iDay + 1;
END;
SELECT #filterDates = STUFF(
(SELECT N''',''' + CONVERT(NVARCHAR, [tempDate], 103) FROM #tempDates FOR XML PATH('')),
1,
2,
''
);
You were on the right track with your suggestion. The next query gets your data before you PIVOT it.
SELECT [People].[Person_PersonID], [tempDates].[tempDate], [Attendances].[SignIn], [Attendances].[SignOut],
MIN([Attendances].[SignOut], DATEADD(DAY, 1, [tempDates].[tempDate]))
- MAX([Attendances].[SignIn], [tempDates].[tempDate]) * 24 AS [numHours]
FROM [People]
CROSS JOIN #tempDates [tempDates]
LEFT JOIN [Attendances]
ON (
([Attendances].[SignIn] < DATEADD(DAY, 1, [tempDates].[tempDate]))
AND ([Attendances].[SignOut] > [tempDates].[tempDate])
);
Once we're satisfied with the results of the previous query, we substitute it with a query using PIVOT, which should look something like this.
SELECT *
FROM (
SELECT [People].[PersonID], [tempDates].[tempDate], [Attendances].[SignIn], [Attendances].[SignOut],
MIN([Attendances].[SignOut], DATEADD(DAY, 1, [tempDates].[tempDate]))
- MAX([Attendances].[SignIn], [tempDates].[tempDate]) * 24 AS [numHours]
FROM [People]
CROSS JOIN #tempDates [tempDates]
LEFT JOIN [Attendances]
ON (
([Attendances].[SignIn] < DATEADD(DAY, 1, [tempDates].[tempDate]))
AND ([Attendances].[SignOut] > [tempDates].[tempDate])
)
) AS [DatedAttendance]
PIVOT (
SUM([numHours]) FOR ([tempDate] IN (#filterDates))
) AS [PivotAttendance]
ORDER BY [PersonID]

5 new entries for every existing row

date, product, new_col,
2013/05/16, A,
2013/05/18, A,
2013/06/15, A,
2013/05/16, B,
2013/06/13, B,
2013/06/20, B
I am using SQL Server 2008.
For every existing entry, in new_col I need to store into new_col 5 previous calendar dates up to and including the date in the date column. E.g. for the 1st row in the above table, I need 5/16,5/15,5/14,5/13,5/12 in the new_col.
I have a lot of products in the table and a lot of dates for every product.
I have tried to partition the table based on these two columns but can't figure out a way to enter 5 days in the new_col.
Please help with any suggestions to do this.
WITH cal AS (
SELECT CAST('20130101' AS DATE) as cal_date
UNION ALL
SELECT DATEADD(day, 1, cal_date)
FROm cal
WHERE cal_date < CAST('20131231' AS DATE )
)
SELECT
[date],[product],
new_col = STUFF((SELECT ',' + CONVERT(VARCHAR(10),cal.cal_date,111)
FROM cal
WHERE cal.cal_date BETWEEN DATEADD(day, -4, tbl.[date]) AND tbl.[date]
ORDER BY cal.cal_date DESC
FOR XML PATH('')
),1,1,'')
FROM tbl
OPTION (maxrecursion 0)
sql fiddle demo
I don't know if this is the best solution but it's the first that popped into my head. Also as people have been mentioning, you do not need to store this... you can call this function directly from whatever reporting solution you've deployed. Was lazy about removing the last comma but that's pretty simple. Also feel free to adjust the datetime formatting as you see fit.
CREATE TABLE dbo.Sam ([Date] DATE, Product VARCHAR(10), NewCol VARCHAR(1000))
INSERT INTO dbo.Sam
SELECT '2013/05/16','A',NULL
UNION ALL SELECT '2013/05/18','A',NULL
UNION ALL SELECT '2013/06/15','A',NULL
UNION ALL SELECT '2013/05/16','B',NULL
UNION ALL SELECT '2013/06/13','B',NULL
UNION ALL SELECT '2013/06/20','B',NULL
GO
CREATE FUNCTION dbo.fnGet4PreviousDates(#Date DATE, #Product VARCHAR(10))
RETURNS VARCHAR(1000)
AS
BEGIN
DECLARE #Out VARCHAR(1000) = ''
SELECT #Out = #Out + CONVERT(VARCHAR,[Date],112) + ','
FROM (
SELECT TOP 5 [Date]
FROM dbo.Sam
WHERE Product = #Product
AND [Date] < #Date
ORDER BY [Date] DESC
) t
RETURN #Out
END
GO
UPDATE dbo.Sam
SET NewCol = dbo.fnGet4PreviousDates([Date],Product)
SELECT * FROM dbo.Sam