How to add month name in different columns in sql? - sql

I have this query:
DECLARE #month INT
SET #month=1
SELECT
CLOI_ClientOrderItems.cl_Id,
NoOfInv = SUM(CASE WHEN DATEPART(mm, in_date_issued) <= #month
AND DATEPART(yyyy, in_date_issued) = 2014
THEN 1 ELSE 0 END),
MonthTotal = SUM(CASE WHEN DATEPART(mm, in_date_issued) <= #month
AND DATEPART(yyyy, in_date_issued) = 2014
THEN in_total ELSE 0 END),
Grandtotal = SUM(in_total),
RemainingAmount = SUM(in_total) - SUM(CASE
WHEN DATEPART(mm, in_date_issued) <= #month
THEN in_total ELSE 0 END)
FROM (SELECT
DISTINCT MasterOrderId, cl_Id
FROM
CLOI_ClientOrderItems) as CLOI_ClientOrderItems
INNER JOIN
IN_Invoices
ON
IN_Invoices.MasterOrderId = CLOI_ClientOrderItems.MasterOrderId
GROUP BY
CLOI_ClientOrderItems.cl_id
If I pass month number like 3, it should display it as like Jan Feb and March and its related records in the respective month.
sql
output i want like that:
noofinv amt clid grandtotal jan feb march remainingamt
5 7.00 100000_Pri 245.00 0.00 238.00 7.00 238.00
12 2510.12 100001_pro 181110.29 138891.92 39708.25 2510.12 178600.17

What do you mean when you say display?
This is a query that returns values that are not of type date at all - so where the month should get int?
In the DB the date is being stored as a binary object - so migrating a date to be shown as text is different then running calculations on a date.
you can use DATENAME for that:
http://msdn.microsoft.com/en-us/library/ms174395.aspx
DATEPART - just allows you to take out parts of the date.
http://msdn.microsoft.com/en-us/library/ms174420.aspx
Was I close to answer what you asked?
If I understand correctly - you want to create a dynamic query, that will execute and return results.
So the first part - change your query to be a string, not a query in your code.
SET #SQLQuery = 'SELECT prev_col ,'
Now - concatenate the columns you want in a loop
DECLARE #i AS SMALLINT
SET #i=1;
WHILE (#i <= month)
BEGIN
#SQLQuery = SQLQuery + 'RemainingAmount = SUM(in_total) - SUM(CASE '+
'WHEN DATEPART(mm, in_date_issued) = ' + CONVERT(VARCHAR,#month)+
'THEN in_total ELSE 0 END) AS ' +
DATENAME(month, DATEADD(month, #month, CAST('2008-01-01' AS datetime)))
+', ';
#i=#i+1;
END
#SQLQuery = #SQLQuery + ' .... col >'+ CONVERT(VARCHAR,#month) + ' AS remaining'
#SQLQuery = #SQLQuery + ' from ..... where .....';
afterwards - just execute it:
EXECUTE(#SQLQuery);
again - I don't have a machine to debug it - and make it pretty...
but I think it should be enough for you to get the idea...

Related

How Calculate Expire Date in SQL Query

I have this query for expiry date calculation and its work fine but result show in - eg:-9 year 4 month and 5 day.
I want to show that in normal way like "Expire in 9 years 4 months and 5 day":
DECLARE #TempDate Datetime ,
#ExpiryDate Datetime,
#year int,
#month int,
#day int
SET #ExpiryDate = (SELECT TOP (1) [ExpiryDate] FROM [dbo].[Purchases] WHERE [ProductId] = 1)
SELECT #TempDate = #ExpiryDate
SELECT
#year = DATEDIFF(YEAR, #TempDate, GETDATE()) -
CASE
WHEN (MONTH(#ExpiryDate) > MONTH(GETDATE())) OR
(MONTH(#ExpiryDate) = MONTH(GETDATE()) AND DAY(#ExpiryDate) > DAY(GETDATE()))
THEN 1 ELSE 0
END
SELECT #TempDate = DATEADD(YEAR, #year, #TempDate)
SELECT #month = DATEDIFF(MONTH, #TempDate, GETDATE()) -
CASE
WHEN DAY(#ExpiryDate) > DAY(GETDATE())
THEN 1 ELSE 0
END
SELECT #TempDate = DATEADD(MONTH, #month, #TempDate)
SELECT #day = DATEDIFF(DAY, #TempDate, GETDATE())
SELECT #year AS Years, #month AS Months, #day AS [Days]
If I understand your question correctly, the calculation is working as you expect but you want the Years value to be returned as a positive rather than negative number. If this is the case, you should change the final SELECT to:
SELECT (#year * -1) AS Years, #month AS Months, #day AS [Days];
Alternatively if you want to return the output as a string (i.e. Expire in 9 years 4 months and 5 day), change the final SELECT to:
SELECT 'Expire in ' + CAST((#year * -1) AS VARCHAR(2)) + ' years '
+ CAST(#month AS VARCHAR(2)) + ' months and '
+ CAST(#day AS VARCHAR(2)) + ' day';
Casting as VARCHAR(2) assumes that you expect no more than 99 years, but you may want to increase that number.

Calculating age in a certain month in SQL Server

I need to extraxt a list of users who turn 15 years old in any day in a certain month (e.g. in June or in July) and I am trying to use string comparison in SQL Server (stored procedure) but it is not working.
I get #Month parameter from a SSRS which is given from a dropdown list of next 10 months. (some of this month will be in the next year).
I have an Age function which converts a date format from 27/07/2003 (BirthDate) to a string 15 years,2 months,27 days. Naturally, There are people aged 9 years, 0 months, 2 days as well.
So far, I could write the code to check if the person will be 15 and at least 1 month (15 years,1 months) in next July (#Month + 1) supposing we want to know if they turn 15 in June (#Month) but still it is not working because of string comparison.
Age(BirthDate, GETDATE()) is the function which turns age in this format:
15 years,2 months,27 days as string.
I hope it is clear what I mean.
declare #Age varchar (20) = 15,
#Month varchar (25) = 'June',
#CurrentMonth varchar (20) = null,
SET #CurrentMonth = DATENAME(month, GETDATE()); /* returns current month in string */
SELECT My_ID
,Title
,FirstName
,LastName
,Gender
,CONVERT(VARCHAR, BirthDate, 103) AS BirthDate
,dbo.Age(BirthDate, GETDATE()) AS Age
,LocalityName AS Locality
,GETDATE() AS ReportDate
,MONTH(GETDATE()) AS MONTH
,YEAR(GETDATE()) AS YEAR
FROM dbo.vw_individuals
WHERE (LEFT(dbo.Age(BirthDate, DATEADD(month, 1 +
(SELECT DATEDIFF(MONTH, #CurrentMonth + ' 01 2010', #Month + ' 01 2010')
+ CASE WHEN DATEDIFF(MONTH, #CurrentMonth + ' 01 2010', #Month + ' 01 2010') < 0 THEN 12 ELSE 0 END)
, GETDATE())), 2) = #Age)
AND (LEFT(dbo.Age(BirthDate, DATEADD(month, 1 +
(SELECT DATEDIFF(MONTH, #CurrentMonth + ' 01 2010', #Month + ' 01 2010')
+ CASE WHEN DATEDIFF(MONTH, #CurrentMonth + ' 01 2010', #Month + ' 01 2010') < 0 THEN 12 ELSE 0 END)
, GETDATE())), 16) < #Age + ' years,2 month')
AND (month(convert(DATETIME, BirthDate, 103)) = (SELECT DATEPART(MM, #Month + '01 2010'))) /* Checks if the BirthDate month is the same as the chosen month (#Month) */
so given the #Month and #Year you're interested in, then the people you need are given BY
SELECT ..... WHERE YEAR(BirthDate) = #YEAR - 15 AND Month(BirthDate) = #Month
so all the people returned have a 15th birthday in #Month/#Year
-- bit of a pain though, might not quite work if a person is born 29th February, they turn 15 in March although that will never be a leap year, so you could get away with
SELECT ..... WHERE YEAR(BirthDate) = #YEAR - 15
AND Month(BirthDate)
+ CASE WHEN MONTH(Birthdate) = 2 AND DAY(Birthdate) = 29 THEN 1 ELSE 0 END
= #Month
Below should show you way to go, your query is much too complicated for what you need (I think), just use logic from my IF in your WHERE
declare #dob datetime = '2003-10-13 17:21:45.620'
if(month(#dob) = month(getdate())
AND year(#dob)+15 = year(getdate()))
print '15 years old this month'
else
print 'not 15 years old this month'
The same yoke, just used table variable:
declare #dob datetime = '2003-10-13 17:21:45.620'
declare #t table (dob datetime)
insert into #t
values ('2003-10-13 17:21:45.620'), ('2004-10-13 17:21:45.620'), ('2003-10-30 17:21:45.620')
select *
from #t
where month(dob) = month(getdate())
and year(dob)+15 = year(getdate())
EDIT
Other way to achieve what you need is to use DATEDIFF
declare #dob datetime = '2003-10-13 17:21:45.620'
declare #t table (dob datetime)
insert into #t
values ('2003-10-13 17:21:45.620'),
('2004-10-13 17:21:45.620'),
('2003-10-30 17:21:45.620')
select *
from #t
where datediff(month, dob, getdate()) = 180 --(15 years * 12months)

Get day of the week in month (2nd Tuesday, etc.)

I need an algorithm for calculating the number of the day of the week in the month. Like 1st Friday of the month, 3rd Monday of the month, etc.)
Any ideas are appreciated.
Here is the final result:
declare #dt date = GetDate()
declare #DayOfWeek tinyint = datepart(weekday,#dt)
declare #DayOfMonth smallint = day(#dt)
declare #FirstDayOfMonth date = dateadd(month,datediff(month,0,#dt),0)
declare #DayOfWeekInMonth tinyint = #DayOfMonth / 7 + 1 -
(case when day(#FirstDayOfMonth) > day(#dt) then 1 else 0 end)
declare #Suffix varchar(2) =
case
when #DayOfWeekInMonth = 1 then 'st'
when #DayOfWeekInMonth = 2 then 'nd'
when #DayOfWeekInMonth = 3 then 'rd'
when #DayOfWeekInMonth > 3 then 'th'
end
select
cast(#DayOfWeekInMonth as varchar(2))
+ #Suffix
+ ' '
+ datename(weekday,#Dt)
+ ' of '
+ datename(month,#dt)
+ ', '
+ datename(year,#Dt)
PS: And if you can think of a better way to state the problem, please do.
Followint code will give you 1st Wednesday of April 2014 for today:
SELECT cast((DATEPART(d, GETDATE() - 1) / 7) + 1 as varchar(12))
+ 'st ' + DATENAME(WEEKDAY, getdate()) + ' of ' +
DATENAME(month, getdate()) + ' ' + DATENAME(year, getdate());
For any date use the code below. It gives 5th Tuesday of April 2014 for #mydate = '2014-04-29' in the example:
DECLARE #mydate DATETIME;
SET #mydate = '2014-04-29';
SELECT
case
when DATEPART(d, #mydate) = 1 then cast((DATEPART(d, #mydate ) / 7) + 1 as varchar(12))
else cast((DATEPART(d, #mydate - 1) / 7) + 1 as varchar(12))
end
+
case
when (DATEPART(d, #mydate - 1) / 7) + 1 = 1 then 'st '
when (DATEPART(d, #mydate - 1) / 7) + 1 = 2 then 'nd '
when (DATEPART(d, #mydate - 1) / 7) + 1 = 3 then 'rd '
else 'th '
end
+ DATENAME(WEEKDAY, #mydate) + ' of ' +
DATENAME(month, #mydate) + ' ' + DATENAME(year, #mydate) as [Long Date Name]
Okeeeey my tuuuurn ,
Please rate my answer Metaphor hhh, Here's the cooode :
declare #v_month nvarchar(2) = '04'
,#v_annee nvarchar(4) = '2014'
declare #v_date date = convert(date,#v_annee+'-'+#v_month+'-01')
declare #v_date_2 date = dateadd(M,1,#v_date)
if OBJECT_ID('temp') is not null
drop table temp
create table temp(_date date, _DayOfMonth nvarchar(20), _order int)
while (#v_date<#v_date_2)
begin
set #v_date =#v_date;
WITH _DayOfWeek AS (
SELECT 1 id, 'monday' Name UNION ALL
SELECT 2 id, 'tuesday' Name UNION ALL
SELECT 3 id, 'wednesday' Name UNION ALL
SELECT 4 id, 'thursday' Name UNION ALL
SELECT 5 id, 'friday' Name UNION ALL
SELECT 6 id, 'saturday' Name UNION ALL
SELECT 7 id, 'sunday' Name)
insert into temp(_date,_DayOfMonth)
SELECT
#v_date
,(select Name from _DayOfWeek where id = DATEPART(WEEKDAY,#v_date))
SET #v_date = DATEADD(DAY,1,#v_date)
END
UPDATE tmp1
SET _order = _order_2
FROM temp tmp1
INNER JOIN
(SELECT *, ROW_NUMBER() OVER(PARTITION BY _DayOfMonth ORDER BY _date ASC) AS _order_2 FROM temp) tmp2
ON tmp1._date = tmp2._date
SELECT * FROM temp
SELECT *
FROM temp
WHERE _DayOfMonth = 'thursday'
AND _order = 3
I hope this will help you :)
Good Luck
OK, here's what I came up with, I'll +1 everyone who answered anyway:
declare #dt date = GetDate()
declare #DayOfWeek tinyint = datepart(weekday,#dt)
declare #DayOfMonth smallint = day(#dt)
declare #FirstDayOfMonth date = dateadd(month,datediff(month,0,#dt),0)
declare #DayOfWeekInMonth tinyint =
#DayOfMonth / 7 + 1
- (case when day(#FirstDayOfMonth) > day(#dt) then 1 else 0 end)
declare #Suffix varchar(2) =
case
when #DayOfWeekInMonth = 1 then 'st'
when #DayOfWeekInMonth = 2 then 'nd'
when #DayOfWeekInMonth = 3 then 'rd'
when #DayOfWeekInMonth > 3 then 'th'
end
select
cast(#DayOfWeekInMonth as varchar(2))
+ #Suffix
+ ' '
+ datename(weekday,#Dt)
+ ' of '
+ datename(month,#dt)
+ ', '
+ datename(year,#Dt)
declare #dt date = getdate()
declare #DayOfMonth smallint = datepart(d, #dt)
declare #Suffix varchar(2) =
case
when floor((#DayOfMonth - 1) / 7.0) = 0 then 'st' -- implies there were no such days previously in the month
when floor((#DayOfMonth - 1) / 7.0) = 1 then 'nd'
when floor((#DayOfMonth - 1) / 7.0) = 2 then 'rd'
else 'th'
end
select cast(floor((#DayOfMonth - 1) / 7.0) + 1 as varchar(1)) + #Suffix +
' ' + datename(weekday, #dt) + ' of ' + datename(month, #dt) +
', ' + datename(year, #dt)
DECLARE #dt DATETIME
SET #dt = DATEADD(d, 6, GETDATE())
SELECT #dt,
CAST((DAY(#dt) / 7) + CASE WHEN DATEPART(weekday, #dt) >= DATEPART(weekday, CAST(MONTH(#dt) AS NVARCHAR) + '/01/' + CAST(YEAR(#dt) AS NVARCHAR)) THEN 1 ELSE 0 END AS NVARCHAR)
+ '' + CASE (DAY(#dt) / 7) + CASE WHEN DATEPART(weekday, #dt) >= DATEPART(weekday, CAST(MONTH(#dt) AS NVARCHAR) + '/01/' + CAST(YEAR(#dt) AS NVARCHAR)) THEN 1 ELSE 0 END
WHEN 1 THEN N'st'
WHEN 2 THEN N'nd'
WHEN 3 THEN N'rd'
ELSE N'th'
END
+ ' ' + DATENAME(dw, #dt)
+ ' of ' + DATENAME(M, #dt)
+ ', ' + CAST(YEAR(#dt) AS NVARCHAR)
Result is a single SELECT (provided the assignment of #dt happened earlier) but is, essentially, the same logic as yours.
This following code will give you DATE for any day of the week in any month or year that you specify. All the variables that I have are to reduce repeating logic to improve code speed.
This code gives you date for 1st Monday in February in 2013
DECLARE #DayNumber INT = 1
,#DayWeekNumber INT = 2
,#MonthNumber INT = 2
,#YearNumber INT = 2013
,#FoM DATE
,#FoMWD INT;
SET #FoM = DATEFROMPARTS(#YearNumber,#MonthNumber,1)
SET #fomwd = DATEPART(WEEKDAY, #FoM);
SELECT CASE WHEN #fomwd = #DayWeekNumber THEN DATEADD(WEEK, #DayNumber - 1, #FoM)
WHEN #fomwd < #DayWeekNumber THEN DATEADD(DAY, #DayWeekNumber - #fomwd, DATEADD(WEEK, #DayNumber - 1, #FoM))
WHEN #fomwd > #DayWeekNumber THEN DATEADD(DAY, #DayWeekNumber - #fomwd, DATEADD(WEEK, #DayNumber, #FoM))
END AS DateOfDay;

INNER JOIN code calculated value with SELECT statement

I have the following stored procedure which will generate mon to sun and then creates a temp table with a series of 'weeks' (start and end weeks) :
USE [test_staff]
GO
/****** Object: StoredProcedure [dbo].[sp_timesheets_all_staff_by_week_by_job_grouping_by_site] Script Date: 03/21/2012 09:04:49 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[sp_timesheets_all_staff_by_week_by_job_grouping_by_site]
(
#grouping_ref int,
#week_ref int
)
AS
CREATE TABLE #WeeklyList
(
Start_Week date,
End_Week date,
week_ref int
--month_name date
)
DECLARE #REPORT_DATE DATETIME, #WEEK_BEGINING VARCHAR(10)
SELECT #REPORT_DATE = '2011-01-19T00:00:00'
--SELECT #REPORT_DATE = GETDATE() -- should grab the date now.
SELECT #WEEK_BEGINING = 'MONDAY'
IF #WEEK_BEGINING = 'MONDAY'
SET DATEFIRST 1
ELSE IF #WEEK_BEGINING = 'TUESDAY'
SET DATEFIRST 2
ELSE IF #WEEK_BEGINING = 'WEDNESDAY'
SET DATEFIRST 3
ELSE IF #WEEK_BEGINING = 'THURSDAY'
SET DATEFIRST 4
ELSE IF #WEEK_BEGINING = 'FRIDAY'
SET DATEFIRST 5
ELSE IF #WEEK_BEGINING = 'SATURDAY'
SET DATEFIRST 6
ELSE IF #WEEK_BEGINING = 'SUNDAY'
SET DATEFIRST 7
DECLARE #WEEK_START_DATE DATETIME, #WEEK_END_DATE DATETIME
--GET THE WEEK START DATE
SELECT #WEEK_START_DATE = #REPORT_DATE - (DATEPART(DW, #REPORT_DATE) - 1)
--GET THE WEEK END DATE
SELECT #WEEK_END_DATE = #REPORT_DATE + (7 - DATEPART(DW, #REPORT_DATE))
PRINT 'Week Start: ' + CONVERT(VARCHAR, #WEEK_START_DATE)
PRINT 'Week End: ' + CONVERT(VARCHAR, #WEEK_END_DATE)
DECLARE #Interval int = datediff(WEEK,getdate(),#WEEK_START_DATE)+1
--SELECT Start_Week=#WEEK_START_DATE
--, End_Week=#WEEK_END_DATE
--INTO #WeekList
INSERT INTO #WeeklyList
SELECT Start_Week=#WEEK_START_DATE, End_Week=#WEEK_END_DATE
WHILE #Interval <= 0
BEGIN
set #WEEK_START_DATE=DATEADD(WEEK,1,#WEEK_START_DATE)
set #WEEK_END_DATE=DATEADD(WEEK,1,#WEEK_END_DATE)
INSERT INTO #WeeklyList values (#WEEK_START_DATE,#WEEK_END_DATE)
SET #Interval += 1;
END
SELECT
CONVERT(VARCHAR(11), Start_Week, 106) AS 'month_name',
CONVERT(VARCHAR(11), End_Week, 106) AS 'End',
DATEDIFF(DAY, 0, Start_Week) / 7 AS week_ref -- create the unique week reference number
--'VIEW' AS month_name
FROM #WeeklyList
In this section i am creating the week_ref
DATEDIFF(DAY, 0, Start_Week) / 7 AS week_ref -- create the unique week reference number
I then need to combine it with this select code:
DECLARE #YearString char(3) = CONVERT(char(3), SUBSTRING(CONVERT(char(5), #week_ref), 1, 3))
DECLARE #MonthString char(2) = CONVERT(char(2), SUBSTRING(CONVERT(char(5), #week_ref), 4, 2))
--Convert:
DECLARE #Year int = CONVERT(int, #YearString) + 1200
DECLARE #Month int = CONVERT(int, #MonthString)
**--THIS FILTERS THE REPORT**
SELECT ts.staff_member_ref, sm.common_name, sm.department_name, DATENAME(MONTH, ts.start_dtm) + ' ' + DATENAME(YEAR, ts.start_dtm) AS month_name,
ts.timesheet_cat_ref, cat.desc_long AS timesheet_cat_desc, grps.grouping_ref, grps.description AS grouping_desc, ts.task_ref, tsks.task_code,
tsks.description AS task_desc, ts.site_ref, sits.description AS site_desc, ts.site_ref AS Expr1,
CASE WHEN ts .status = 0 THEN 'Pending' WHEN ts .status = 1 THEN 'Booked' WHEN ts .status = 2 THEN 'Approved' ELSE 'Invalid Status' END AS site_status,
ts.booked_time AS booked_time_sum,
start_dtm, CONVERT(varchar(20), start_dtm, 108) + ' ' + CONVERT(varchar(20), start_dtm, 103) AS start_dtm_text, booked_time,
end_dtm, CONVERT(varchar(20), end_dtm, 108) + ' ' + CONVERT(varchar(20), end_dtm, 103) AS end_dtm_text
FROM timesheets AS ts INNER JOIN
timesheet_categories AS cat ON ts.timesheet_cat_ref = cat.timesheet_cat_ref INNER JOIN
timesheet_tasks AS tsks ON ts.task_ref = tsks.task_ref INNER JOIN
timesheet_task_groupings AS grps ON tsks.grouping_ref = grps.grouping_ref INNER JOIN
timesheet_sites AS sits ON ts.site_ref = sits.site_ref INNER JOIN
vw_staff_members AS sm ON ts.staff_member_ref = sm.staff_member_ref
WHERE (ts.status IN (1, 2)) AND (cat.is_leave_category = 0)
GROUP BY ts.staff_member_ref, sm.common_name, sm.department_name, DATENAME(MONTH, ts.start_dtm), DATENAME(YEAR, ts.start_dtm), ts.timesheet_cat_ref,
cat.desc_long, grps.grouping_ref, grps.description, ts.status, ts.booked_time, ts.task_ref, tsks.task_code, tsks.description, ts.site_ref, sits.description, ts.start_dtm,
ts.end_dtm
ORDER BY sm.common_name, timesheet_cat_desc, tsks.task_code, site_desc
DROP TABLE #WeeklyList
GO
I want to pass the week_ref into the SELECT statement (refer to comment - THIS FILTERS THE REPORT) but the problem is week_ref isnt a valid column as its derived by code.
Any ideas?
Just perform an INNER JOIN to your weeklylist temp table on the date you need to filter.
I am not sure that I really understand the problem but I found 2 problems in the code you posted.
The inserts you make on the #WeeklyList temporary table, are missing one column in the selected values that I assume you wanted to be your variable #week_ref
I I change this, I get to the point of the final table select that I dont have.
hope this is a start to solve your problem

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