Date functions in Stored Procedure - sql

Overview : I want to show the weekly result by input parameters startdate and enddate. I am getting this result quite well. But the problem here is, When i want start date from 28/08/2015 from end date 04/09/2015 am getting 28, 29, 30, 31, 01, 02, 03, 04 from same month(august). Expected result should be 28, 29, 30, 31 from august and 01, 02, 03, 04 from september.
Help me to overcome this problem. Below is my code
ALTER PROCEDURE [dbo].[usp_Get_TimesheetDetails]
#UserID int, #startdate datetime, #enddate datetime
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
declare #intStartDate int
declare #intEndDate int, #diff int
declare #strMonth varchar(50)
Select #intStartDate = DATEPART(day, #startDate)
Select #intEndDate = DATEPART(day, #endDate)
select #strMonth = DATENAME(MONTH, GETDATE())
Declare #temptable table (num date )
Declare #columns varchar(max)
DECLARE #sqlText nvarchar(1000);
DECLARE #startnum INT = #intStartDate-1
DECLARE #endnum INT = #intEndDate
select #diff = DATEDIFF(MONTH, #startdate, #enddate)
;WITH gen AS (
SELECT #startdate AS num
UNION ALL
SELECT DATEADD(DAY,1,num) FROM gen
WHERE DATEADD(DAY,1,num) <= #enddate
)
insert into #temptable SELECT num FROM gen
option (maxrecursion 10000)
set #columns=
(SELECT distinct
STUFF((SELECT ',' + CAST( DATEPART(DAY, num) as varchar(100)) [text()]
FROM #temptable
FOR XML PATH(''), TYPE)
.value('.','NVARCHAR(MAX)'),1,2,' ') List_Output
FROM #temptable t)
if(#startnum < 10)
BEGIN
SET #sqlText = N'SELECT ' + STUFF(REPLACE(#columns,',','],['),1,3,'') + ']' + ' FROM dbo.timesheet where month ='''+ #strMonth+''' and [Task ID] in(select TaskID from ManageTasks where TeamMemberUserID ='+ Cast(#UserID AS VARCHAR(max)) +')'
print #sqlText
END
else if(#startnum >= 10)
BEGIN
SET #sqlText = N'SELECT ' + STUFF(REPLACE(#columns,',','],['),1,4,'') + ']' + ' FROM dbo.timesheet where month ='''+ #strMonth+''' and [Task ID] in(select TaskID from ManageTasks where TeamMemberUserID ='+ Cast(#UserID AS VARCHAR(max)) +')'
END
print #sqlText
Exec (#sqlText)
end
end
Edited : I tried with if else condition like, if(monthdifference is equal to 0)
else(monthdifference is greater than 0). But not getting expected result.

try this
Declare
#StartDate datetime='2015/08/28',
#EndDate datetime='2015/09/04'
;WITH sample AS (
SELECT CAST(#StartDate AS DATETIME) AS dt
UNION ALL
SELECT DATEADD(dd, 1, dt)
FROM sample s
WHERE DATEADD(dd, 1, dt) <= CAST(#EndDate AS DATETIME))
SELECT *
FROM sample
output is :
2015-08-28 00:00:00.000
2015-08-29 00:00:00.000
2015-08-30 00:00:00.000
2015-08-31 00:00:00.000
2015-09-01 00:00:00.000
2015-09-02 00:00:00.000
2015-09-03 00:00:00.000
2015-09-04 00:00:00.000
Original Link : https://stackoverflow.com/a/3946151/3465753

Make sure you declared startdate as well as enddate in dynamic query

The main Ideas are:
You don't need to use STUFF. Just select dates from DATEADD(DAY,1,#startdate)
You should get dates twise if DATENAME(MONTH, #startdate)!=DATENAME(MONTH, #enddate). First time from startdate to end of months. Second time from start of second month to enddate.
My (checked) script.
ALTER PROCEDURE [dbo].[usp_Get_TimesheetDetails]
#UserID int, #startdate datetime, #enddate datetime
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
Declare #columns varchar(max);
DECLARE #sqlText nvarchar(1000);
Declare #temptable table (num date );
WITH gen AS (
SELECT DATEADD(DAY,1,#startdate) AS num
UNION ALL
SELECT DATEADD(DAY,1,num) FROM gen
WHERE DATEADD(DAY,1,num) <= #enddate
and DATEADD(DAY,1,num) < dateadd(month,datediff(month,0,#enddate),0)
)
insert into #temptable SELECT num FROM gen
option (maxrecursion 10000)
set #columns=
(SELECT distinct
STUFF((SELECT ',' + CAST( DATEPART(DAY, num) as varchar(100)) [text()]
FROM #temptable
FOR XML PATH(''), TYPE)
.value('.','NVARCHAR(MAX)'),1,1,'') List_Output
FROM #temptable t)
SET #sqlText = N'SELECT [' + REPLACE(#columns,',','],[') + ']' + ' FROM dbo.timesheet where month ='''+ DATENAME(MONTH, #startdate)+''' and [Task ID] in(select TaskID from ManageTasks where TeamMemberUserID ='+ Cast(#UserID AS VARCHAR(max)) +')';
print #sqlText;
IF DATENAME(MONTH, #startdate)!=DATENAME(MONTH, #enddate)
BEGIN
delete from #temptable;
WITH gen AS (
SELECT dateadd(month,datediff(month,0,#enddate),0) AS num
UNION ALL
SELECT DATEADD(DAY,1,num) FROM gen
WHERE DATEADD(DAY,1,num) <= #enddate
)
insert into #temptable SELECT num FROM gen
option (maxrecursion 10000)
set #columns=
(SELECT distinct
STUFF((SELECT ',' + CAST( DATEPART(DAY, num) as varchar(100)) [text()]
FROM #temptable
FOR XML PATH(''), TYPE)
.value('.','NVARCHAR(MAX)'),1,1,'') List_Output
FROM #temptable t)
SET #sqlText = N'SELECT [' + REPLACE(#columns,',','],[') + ']' + ' FROM dbo.timesheet where month ='''+ DATENAME(MONTH, #enddate)+''' and [Task ID] in(select TaskID from ManageTasks where TeamMemberUserID ='+ Cast(#UserID AS VARCHAR(max)) +')';
print #sqlText
end
end

You might find pivot/unpivot to be more robust. Certainly your table design is not ideal. (I pared down the number of columns for demonstration purposes.)
create table dbo.timesheet (
[month] varchar(12) not null,
[1] int null, [2] int null, [3] int null,
[28] int null, [29] int null, [30] int null, [31] int null
);
declare #startDate date = '20160628';
declare #endDate date = '20160703';
insert into dbo.timesheet ([month], [1], [2], [3], [28], [29], [30], [31])
values ('June', 1, 2, 3, 4, 5, 6, null), ('July', 8, 9, 10, 11, 12, 13, 14);
with hrs as (
select
hrs,
dy,
dateadd(
month,
case [month]
when 'January' then 1 when 'February' then 2 when 'March' then 3
when 'April' then 4 when 'May' then 5 when 'June' then 6
when 'July' then 7 when 'August' then 8 when 'September' then 9
when 'October' then 10 when 'November' then 11 when 'December' then 12
end,
dateadd(year, year(getdate()) - 2000, dateadd(day, dy - 1, '19991201'))
) as dt
from
(select [month], [1], [2], [3], [28], [29], [30], [31] from dbo.timesheet) t
unpivot (hrs for dy in ([1], [2], [3], [28], [29], [30], [31])) as upvt
)
select datename(month, dt), [1], [2], [3], [28], [29], [30], [31]
from hrs pivot (min(hrs) for dy in ([1], [2], [3], [28], [29], [30], [31])) as pvt
where dt between #startDate and #endDate;

Related

12 month rolling from a entered month?

Hi can someone please help me, I want to create a script with a month parameter, the results I require is the next 12 month's names as column headings.
For example if the parameter is February the results should be:
March | April | May | June | July | August | September | October | November | December | January | February |
As the column names which I want to use to fill in values at a later stage.
Can someone please advise me on this and how I can achieve this
My script I have so far don't know how to approach this
declare #MonthParam varchar(20) = 'March'
declare #MonthNumber int = (
Select CASE WHEN #MonthParam = 'January' THEN 1
WHEN #MonthParam = 'February' THEN 2
WHEN #MonthParam = 'March' THEN 3
WHEN #MonthParam = 'April' THEN 4
WHEN #MonthParam = 'May' THEN 5
WHEN #MonthParam = 'June' THEN 6
WHEN #MonthParam = 'July' THEN 7
WHEN #MonthParam = 'August' THEN 8
WHEN #MonthParam = 'September' THEN 9
WHEN #MonthParam = 'October' THEN 10
WHEN #MonthParam = 'November' THEN 11
WHEN #MonthParam = 'December' THEN 12
END)
WHILE(#MonthNumber < 13)
BEGIN
declare #month varchar(20) = DateName( month , DateAdd( month , #MonthNumber , 0 ) - 1 )
declare #sql varchar(max)
set #sql = 'select val as ' + #month + ' from t'
exec (#sql)
SET #MonthNumber = #MonthNumber + 1;
END
Other wise you can use the "simplified" approach.
declare #MonthParam varchar(20) = 'March'
declare #Dte date = CAST(concat(#MonthParam, ' 01 1900') AS DATE)
declare #sql varchar(max) = concat('select null as ', DATENAME(MONTH, DATEADD(MONTH, 1, #Dte)),
', null as ', DATENAME(MONTH, DATEADD(MONTH, 2, #Dte)),
',null as ',DATENAME(MONTH, DATEADD(MONTH, 3, #Dte)),
',null as ',DATENAME(MONTH, DATEADD(MONTH, 4, #Dte)),
',null as ',DATENAME(MONTH, DATEADD(MONTH, 5, #Dte)),
',null as ',DATENAME(MONTH, DATEADD(MONTH, 6, #Dte)),
',null as ',DATENAME(MONTH, DATEADD(MONTH, 7, #Dte)),
',null as ',DATENAME(MONTH, DATEADD(MONTH, 8, #Dte)),
',null as ',DATENAME(MONTH, DATEADD(MONTH, 9, #Dte)),
',null as ',DATENAME(MONTH, DATEADD(MONTH, 10, #Dte)),
',null as ',DATENAME(MONTH, DATEADD(MONTH, 11, #Dte)),
',null as ',DATENAME(MONTH, DATEADD(MONTH, 12, #Dte)))
exec (#sql)
declare #date_entered varchar(50) = 'February'
set #date_entered = #date_entered + ' 01 ' + CONVERT(char(4),year(getdate()))
declare #start_month datetime = #date_entered
declare #loop_month datetime = #start_month
declare #sql nvarchar(max)
set #sql = 'CREATE TABLE MyDates ('
WHILE #loop_month < DATEADD(year,1,#start_month)
BEGIN
set #sql += DATENAME(month,#loop_month) + ' varchar(100),'
set #loop_month = DATEADD(month,1,#loop_month)
END
-- Get rid of the comma at the end of the string and close the table paranthesis (edit was to the following bit)
set #sql = LEFT(#sql,len(#sql)-1) + ')'
print #sql
--Uncomment below to run
--exec(#sql)
I've used a temp table with some dummy data to show the final output as a table
DECLARE #PivotColumnHeaders VARCHAR(MAX);
DECLARE #date_entered varchar(50) = 'February';
SET #date_entered = #date_entered + ' 01 ' + CONVERT(CHAR(4),YEAR(GETDATE()));
DECLARE #s INT= 1, #e INT = 12;
CREATE TABLE PivotTemp (Dummy INT, [MonthName] VARCHAR(15));
WHILE ( #s <= #e)
BEGIN
SELECT #PivotColumnHeaders =
COALESCE(
#PivotColumnHeaders + ',[' + DATENAME(MONTH,DATEADD(MONTH, #s, #date_entered)) + ']',
'[' + DATENAME(MONTH,DATEADD(MONTH, #s, #date_entered))+ ']'
);
INSERT INTO PivotTemp ( Dummy, [MonthName] ) VALUES ( #s, DATENAME(MONTH,DATEADD(MONTH, #s, #date_entered)) );
SET #s = #s + 1;
END;
--SELECT #PivotColumnHeaders ;
--SELECT * FROM PivotTemp ;
DECLARE #PivotTableSQL NVARCHAR(MAX);
SET #PivotTableSQL = N'
SELECT *
FROM (
SELECT
H.Dummy [DummyValue],
H.[MonthName] [MonthName]
FROM dbo.PivotTemp H
) AS PivotData
PIVOT (
MAX(DummyValue)
FOR [MonthName] IN (
' + #PivotColumnHeaders + '
)
) AS PivotTable
';
EXECUTE(#PivotTableSQL);
DROP TABLE PivotTemp;

Find Count With Pivot Data SQL Server

I have been displaying Day Wise Attendance Data with Pivot SQL.
declare #startdate datetime = '2016-09-26'
declare #enddate datetime = '2016-10-01'
declare #CompanyID int = 1
DECLARE #COLUMN VARCHAR(MAX), #SQL NVARCHAR(MAX);
SET #COLUMN = N'';
DECLARE #DATERANGE TABLE (DateToCheck DATE)
;WITH Temp
AS
(
SELECT DT =DATEADD(DD,0, #startdate)
WHERE DATEADD(DD, 1, #startdate) <= #enddate
UNION ALL
SELECT DATEADD(DD, 1, DT)
FROM Temp
WHERE DATEADD(DD, 1, DT) <= #enddate
)
INSERT INTO #DATERANGE
SELECT DT From Temp
SELECT #COLUMN += N', T.' + QUOTENAME(DateRanges) FROM (SELECT CAST(CONVERT(DATE, T.DateToCheck) AS VARCHAR(10)) AS DateRanges FROM #DATERANGE T group by T.DateToCheck) AS A;
SET #SQL = '
DECLARE #DATERANGE TABLE (DateToCheck DATE)
;WITH Temp
AS
(
SELECT DT =DATEADD(DD,0, #startdate)
WHERE DATEADD(DD, 1, #startdate) <= #enddate
UNION ALL
SELECT DATEADD(DD, 1, DT)
FROM Temp
WHERE DATEADD(DD, 1, DT) <= #enddate
)
INSERT INTO #DATERANGE
SELECT DT From Temp
SELECT *
FROM (
SELECT E.FirstName, E.LastName, E.Email, T.DateToCheck, COALESCE(A.val, L.val, H.val, ''Absent'') val
FROM AspNetUsers E
CROSS APPLY (
SELECT DateToCheck FROM #DATERANGE
) T--(DateToCheck)
LEFT JOIN (SELECT ''Holiday'' val, HolidayDate, CompanyID FROM Holidays) H ON H.HolidayDate = T.DateToCheck AND H.CompanyID = #CompanyID
LEFT JOIN (SELECT ''In : '' + CONVERT(VARCHAR, MIN(AttendanceDateTime), 108) + '' / Out : '' + CONVERT(VARCHAR, MAX(AttendanceDateTime), 108) val, CAST(AttendanceDateTime As DATE) As AttendanceDate, UserID FROM Attendances GROUP BY CAST(AttendanceDateTime As DATE), UserID) A ON A.AttendanceDate = T.DateToCheck AND A.UserID = E.Id
LEFT JOIN (SELECT ''Leave'' val, LeaveDate, UserID FROM LeaveApplications) L ON L.LeaveDate = T.DateToCheck AND L.UserID = E.Id
WHERE E.CompanyID = #CompanyID
) T
PIVOT (MAX(val) FOR DateToCheck IN (' + STUFF(REPLACE(#COLUMN, ', T.[', ',['), 1, 1, '') + ')) P';
EXEC sp_executesql #SQL, N'#startdate DATE, #enddate DATE, #CompanyID INT', #startdate, #enddate, #CompanyID
And below is the result set of how it's now
Now I wish to add more field to the above SQL to display counts like PresentCount, AbsentCount, HolidayCount and LeaveCount
I have already written a SQL where I could easily display these counts but, I'm unable to make it work with the above PIVOT SQL.
So in this case, the result for first row would be PresentCount = 0, AbsentCount = 6, HolidayCount = 0 and LeaveCount = 0. For Row 2 it would be PresentCount = 4, AbsentCount = 2, LeaveCount and HolidayCount both is 0.

How to create Temp Table with month columns based on date parameters?

I have a stored procedure that accepts two Dates. In my stored procedure, I need to create a temp table with the months in between the two dates as columns.
For example,
If the user passes in
1/1/2016 , 8/1/2016
I need a temp table with the columns:
January February March April May June July August
How could I create this type of temp table with columns created in this manner? With the columns being based on the two dates passed in?
The following script should get you started (and almost there):
declare #start_date DATE = '20160101'
declare #end_date DATE = '20160801'
;WITH CTE AS
(
SELECT #start_date AS cte_start_date, DATENAME(month, #start_date) AS Name,
CAST(' ALTER TABLE #myTemp ADD ' + DATENAME(month, #start_date) + ' INT ' + CHAR(13) + CHAR(10) AS VARCHAR(8000)) AS SqlStr
UNION ALL
SELECT DATEADD(MONTH, 1, cte_start_date), DATENAME(month, DATEADD(MONTH, 1, cte_start_date)) AS Name,
CAST(SqlStr + ' ALTER TABLE #myTemp ADD ' + DATENAME(month, DATEADD(MONTH, 1, cte_start_date)) + ' INT ' + CHAR(13) + CHAR(10) AS VARCHAR(8000))
FROM CTE
WHERE DATEADD(MONTH, 1, cte_start_date) <= #end_date
)
SELECT cte_start_date, Name, SqlStr
FROM CTE
Using a recursive-CTE it generates a loop between start and end date, and for each month it computes its string representation and also creates a alter script to add the columns to a temporary table.
The CTE computes the SQL script gradually, so that the final script is on the last line.
Try This ....
declare #start_date DATE = '20160101'
declare #end_date DATE = '20160801'
;WITH CTE AS
(
SELECT #start_date AS cte_start_date, DATENAME(month, #start_date) AS NAME , 0 AS Coun
UNION ALL
SELECT DATEADD(MONTH, 1, cte_start_date), DATENAME(month, DATEADD(MONTH, 1, cte_start_date)) AS NAME , 0 AS Coun
FROM CTE
WHERE DATEADD(MONTH, 1, cte_start_date) <= #end_date
)
SELECT Coun,Name
INTO #tmp1
FROM CTE
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + Name
from #tmp1
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT ' + #cols + ' from
(
select Coun,Name
from #tmp1
) x
pivot
(
MAX(Coun)
for Name in (' + #cols + ')
) p '
execute(#query);
DROP TABLE #tmp1
It Will Return OutPut Like your expected output .......

SQL Server query to generate dynamic staff attendance report

I have a table to store staff attendance which has the following columns:
id: int, pk
StaffName: varchar
CompanyName: varchar
isPresent: varchar
date: datetime
How do I write a query which gives attendance of a month?
Eg: Generate report for April for a company XYZ, which should looks like
StaffName 1 2 3 4 5 6 7 8 9....up to last day of month
--------------------------------------------------------------
John lenon p p p a p a a p a....
Bob Dylan a a a p p p p p a....
Keith Moon p p p p a p a p p....
That can be a little bit tricky with qynamic queries. For the table:
CREATE TABLE [dbo].[attendance](
[id] [int] NOT NULL,
[StaffName] [varchar](100) NULL,
[CompanyName] [varchar](100) NULL,
[isPresent] [char](1) NULL,
[date] [datetime] NULL,
PRIMARY KEY CLUSTERED ( [id] ASC )
)
go
The following script generates 'pivot-compatible' script with days as columns
--report params
DECLARE #month int, #year int, #lastDay int
set #month = 1
set #year = 2012
-- calculations
DECLARE #startDate datetime, #endDate datetime
SET #startDate = convert(varchar, #year) + '-' + convert(varchar, #month) + '-1'
set #endDate = DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#startDate)+1,0))
set #lastDay = day(#endDate) --last day of month
print('showing data from ' + convert(varchar, #startDate) + ' to ' + convert(varchar, #endDate))
print('original report')
SELECT StaffName, isPresent, day([date]) as day FROM attendance
where [date] between #startDate and #endDate
declare #day int
set #day = 2
declare #days varchar(max)
set #days = '[1]'
WHILE (#day <= #lastDay)
BEGIN
set #days = #days + ',[' + convert(varchar, #day) + ']'
set #day = #day + 1
END
-- select #days
declare #query varchar(max)
set #query = '
SELECT StaffName, ' + #days +
'
FROM
(SELECT StaffName, isPresent, day(date) as day FROM attendance) AS SourceTable
PIVOT
(
MAX(isPresent)
FOR day IN ( ' + #days + ')' + '
) AS PivotTable;'
--select #query
print('pivoted report')
exec(#query)
You can pivot your date as column with the PIVOT functionality(here a quick and dirty example, you may check date format and order):
SELECT StaffName, [0], [1], [2], [3], [4] and so on...
FROM
(SELECT StaffName, isPresent, date FROM myTable) AS SourceTable
PIVOT
(
MAX(isPresent)
FOR date IN ([0], [1], [2], [3], [4] and so on...)
) AS PivotTable;

PIVOT SQL Data & Fill In Blanks

I'm attempting to transform this data:
ItemID MonthAsInt Month Year InvType Quantity
4643 4 April 2011 Shipment 10
4643 5 May 2011 Shipment 10
4643 7 July 2011 Shipment 10
4643 8 August 2011 Destroy 10
4643 11 November 2011 Shipment 25
4643 12 December 2011 Picking 1
Into this (basically, a 12 month snap shot):
February March April May June July August ...
Shipment 0 0 10 10 0 10 0
Picking 0 0 0 0 0 0 0
Destroy ...
I've messed with the PIVIOT method, but I haven't had much luck. At this point, all I have is the list of dates that I need between GETDATE() and GETDATE() - 12 months (retrieved with the query below):
DECLARE #BeginDate DATETIME
DECLARE #EndDate DATETIME
SET #BeginDate = GETDATE();
SET #EndDate = DATEADD(MONTH, -12, GETDATE());
WITH CTE_DatesTable
AS
(
SELECT #EndDate AS [Date]
UNION ALL
SELECT DATEADD(dd, 1, [date])
FROM CTE_DatesTable
WHERE DATEADD(dd, 1, [date]) <= #BeginDate
)
SELECT DISTINCT DATENAME(MONTH, [date]) + ' '
+ CAST(YEAR([date]) AS VARCHAR(4)) AS MonthYear,
YEAR([date]) AS YearAsInt,
MONTH([Date]) AS MonthAsInt
FROM CTE_DatesTable
ORDER BY YEAR([date]), MONTH([Date])
OPTION (MAXRECURSION 0)
See the query in action here.
Is what I'm trying to accomplish possible? Am I going in the right direction? Any help would be appreciated!
You can do this without pivot (the syntax for which I find daunting as well). Since you don't know the actual layout of columns beforehand, I think this is easiest with dynamic SQL. Given the following table/sample data:
USE tempdb;
GO
CREATE TABLE dbo.foo
(
ItemID INT,
MonthAsInt INT,
[Month] VARCHAR(12),
[Year] INT,
InvType VARCHAR(12),
Quantity INT
);
INSERT dbo.foo SELECT 4643,4 ,'April ',2011,'Shipment',10
UNION ALL SELECT 4643,5 ,'May ',2011,'Shipment',10
UNION ALL SELECT 4643,7 ,'July ',2011,'Shipment',10
UNION ALL SELECT 4643,8 ,'August ',2011,'Destroy ',10
UNION ALL SELECT 4643,11,'November',2011,'Shipment',25
UNION ALL SELECT 4643,12,'December',2011,'Picking ',1;
You can generate a list of months using a much simpler CTE, and build a dynamic SQL statement based off of that:
DECLARE #sql NVARCHAR(MAX) = N'';
;WITH n AS
(
SELECT TOP (12) d = DATEADD
(
MONTH,
-(ROW_NUMBER() OVER (ORDER BY [object_id]) - 1),
GETDATE()
)
FROM sys.objects
ORDER BY d DESC
)
SELECT #sql = #sql + N',' + CHAR(13) + CHAR(10) + DATENAME(MONTH, d)
+ ' = SUM(CASE WHEN [Year] = ' + CONVERT(VARCHAR(4), DATEPART(YEAR, d))
+ ' AND MonthAsInt = ' + CONVERT(VARCHAR(2), DATEPART(MONTH, d))
+ ' THEN Quantity ELSE 0 END)'
FROM n
ORDER BY d;
SELECT #sql = N'SELECT InvType' + #sql + '
FROM dbo.foo
GROUP BY InvType';
PRINT #sql;
-- EXEC sp_executesql #sql;
I put the PRINT there so you could test it out before running it. I wasn't sure if you needed 12 months or 13 months, you can just change the TOP (12) to TOP (13) if you want 13 months, or remove the -1 if you don't want the current month included.
If you need a dynamic pivot: see here
otherwise
This is how you do it will pivot. Of course, PIVOT requires you to know what your data will look like beforehand. If you need a dynamic pivot, then there are plenty of dynamic crosstab/pivot queries/sps that people have already written.
DECLARE #BeginDate DATETIME
DECLARE #EndDate DATETIME
SET #BeginDate = GETDATE();
SET #EndDate = DATEADD(MONTH, -12, GETDATE());
WITH CTE_DatesTable
AS
(
SELECT #EndDate AS [Date]
UNION ALL
SELECT DATEADD(dd, 1, [date])
FROM CTE_DatesTable
WHERE DATEADD(dd, 1, [date]) <= #BeginDate
)
SELECT DISTINCT DATENAME(MONTH, [date]) + ' ' + CAST(YEAR([date]) AS VARCHAR(4)) AS MonthYear,
YEAR([date]) AS YearAsInt,
MONTH([Date]) AS MonthAsInt,
case when month([date]) < 5 then 'Shipment' else 'Picking' end InvType,
floor(10 * RAND() * month([date])) Quantity
into #orig
FROM CTE_DatesTable
ORDER BY YEAR([date]), MONTH([Date])
OPTION (MAXRECURSION 0)
update #orig
set Quantity = null
where MonthYear = 'February 2011'
select * from #orig
select *
from
(
select isnull(Quantity, 0) Quantity, MonthYear from #orig
) SourceTbl
PIVOT
(
sum(Quantity)
for MonthYear in ([February 2011], [March 2011])
) PivotTbl
drop table #orig
Result:
February 2011 March 2011
0 29