I am having trouble outputting an SQL Select Statement to my XML to be used for my Graph
I have these results
December 2011 470 FRESENIUS
January 2012 434 FRESENIUS
February 2012 278 FRESENIUS
February 2012 2 STORESID
I need to output them like this so I can loop my Code and generate the XML
Month Year FRESNIUS STORESID
December 2011 470 0
January 2012 434 0
February 2012 278 2
take note i did not include the headers, these are all column results.
and also, STORESID and FRESNIUS are not STATIC Values. Multiple Storers Exists so I needed to Expand my number of Columns also , Dynamically.
I kinda need to output the second one to generate the XML properly thru PHP which I already have. Or are there any other proper way.
Thanks.
query below for the output i was talking about
SELECT
DATENAME(month, orderdate) + ' ' + CAST(Year(orderdate) AS VARCHAR(4)) AS 'Month Year' ,
count(*) 'Number of Orders',
storerkey
FROM orders
GROUP BY
storerkey,
DATENAME(month, orderdate) + ' ' + CAST(Year(orderdate) AS VARCHAR(4)),
CAST(Year(orderdate) AS VARCHAR(4)) + RIGHT('0' + CAST(Month(orderdate) AS VARCHAR(2)),2)
ORDER BY
storerkey,
CAST(Year(orderdate) AS VARCHAR(4)) + RIGHT('0' + CAST(Month(orderdate) AS VARCHAR(2)),2)
I am not 100% certain of the XML output you need but you can take advantage of SQL-Servers FOR XML clause and PIVOT function. This should get you started:
CREATE TABLE #Test (GraphDate DATETIME, Value INT, Type VARCHAR(50))
INSERT #Test VALUES
('01/12/2011', 470, 'FRESENIUS'),
('01/01/2012', 434, 'FRESENIUS'),
('01/12/2012', 278, 'FRESENIUS'),
('01/02/2012', 2, 'STORESID')
SELECT DATEPART(YEAR, GraphDate) [Year],
DATENAME(MONTH, GraphDate) [Month],
ISNULL(FRESENIUS, 0) [FRESENIUS],
ISNULL(STORESID, 0) [STORESID]
FROM #Test
PIVOT
( SUM(Value)
FOR Type IN ([FRESENIUS], [STORESID])
) PivotTable
FOR XML PATH('row'), ROOT
DROP TABLE #Test
EDIT
The below is the basic query you have asked for based on the query you have given.
SELECT DATENAME(MONTH, OrderDate) + ' ' + DATENAME(YEAR, OrderDate) [MonthYear],
ISNULL(FRESENIUS, 0) [FRESENIUS],
ISNULL(STORESID, 0) [STORESID]
FROM Orders
PIVOT
( COUNT(StorerKey)
FOR StorerKey IN ([FRESENIUS], [STORESID])
) PivotTable
ORDER BY DATEPART(YEAR, OrderDate), DATEPART(MONTH, OrderDate)
EDIT 2
I don't think PIVOT is supported by SQL-Server 2000. You will need to use aggregate functions:
SELECT DATENAME(MONTH, OrderDate) + ' ' + DATENAME(YEAR, OrderDate) [MonthYear],
COUNT(CASE WHEN StorerKey = 'FRESENIUS' THEN 1 END) [FRESENIUS],
COUNT(CASE WHEN StorerKey = 'STORESID' THEN 1 END) [STORESID]
FROM Orders
GROUP BY DATEPART(YEAR, OrderDate), DATEPART(MONTH, OrderDate), DATENAME(YEAR, OrderDate), DATENAME(MONTH, OrderDate)
ORDER BY DATEPART(YEAR, OrderDate), DATEPART(MONTH, OrderDate)
I think some FOR XML functionality is still available though so you may still be able to output your XML directly from SQL.
EDIT 3
DECLARE #SQL NVARCHAR(2000)
SELECT #SQL = ISNULL(#SQL, '') + ', COUNT(CASE WHEN StorerKey = ''' + StorerKey + ''' THEN 1 END) [' + StorerKey + ']'
FROM ( SELECT DISTINCT StorerKey
FROM Orders
) Keys
SET #SQL = 'SELECT DATENAME(MONTH, OrderDate) + '' '' + DATENAME(YEAR, OrderDate) [MonthYear]' + #SQL +
' FROM Orders
GROUP BY DATEPART(YEAR, OrderDate), DATEPART(MONTH, OrderDate), DATENAME(YEAR, OrderDate), DATENAME(MONTH, OrderDate)
ORDER BY DATEPART(YEAR, OrderDate), DATEPART(MONTH, OrderDate)'
EXECUTE SP_EXECUTESQL #SQL
You could join the table to itself. If I make assumptions about the column names, assume that either the FRESNIUS or STORESID could be absent, and use common table expressions (untested!):
WITH date_fresnius AS (
SELECT [Month Year], FRESNIUS
FROM original_table
)
, date_storesid AS (
SELECT [Month Year], STORESID
FROM original_table
)
SELECT
ISNULL( f.[Month Year], s.[Month Year]) AS [Month Year]
, ISNULL( f.FRESNIUS, 0 ) AS FRESNIUS
, ISNULL( s.STORESID, 0 ) AS STORESID
FROM
date_fresnius f
FULL OUTER JOIN date_storesid s ON (f.[Month Year] = s.[Month Year])
If you always have a FRESNIUS record you can use a LEFT JOIN instead.
Based on your query:
SELECT
DATENAME(MONTH, orderdate) + ' ' + CAST(YEAR(orderdate) AS VARCHAR(4)) AS [Month Year]
COUNT(CASE storerkey WHEN 'FRESNIUS' THEN 1 END) AS FRESNIUS,
COUNT(CASE storerkey WHEN 'STORESID' THEN 1 END) AS STORESID
FROM orders
GROUP BY YEAR(orderdate), MONTH(orderdate), DATENAME(MONTH, orderdate)
ORDER BY YEAR(orderdate), MONTH(orderdate)
Output:
Month Year FRESNIUS STORESID
December 2011 470 0
January 2012 434 0
February 2012 278 2
Related
I need a simple output of fields named "36" - "1" with the extended inventory value for everything in the specified item classes. I don't need itemization.
E.g.
Error is:
"Database Connector Error. '42000:[Microsoft][ODBC SQL Server Driver][SQL Server]The multi-part identifier "InvenFiscPerHistTable.FiscalPeriod" could no be bound. [Database Vendor Code: 4104 ]'
Here's my SQL.
DECLARE #CalMonth INT
DECLARE #CalYear INT
DECLARE #CalMoYear DATETIME
SET #CalMonth = CASE WHEN "InvenFiscPerHistTable"."FiscalPeriod" IN (1,2,3) THEN "InvenFiscPerHistTable"."FiscalPeriod" + 9 ELSE "InvenFiscPerHistTable"."FiscalPeriod" - 3 END
SET #CalYear = CASE WHEN "InvenFiscPerHistTable"."FiscalPeriod" IN (1,2,3) THEN "InvenFiscPerHistTable"."FiscalYear" + 1 ELSE "InvenFiscPerHistTable"."FiscalYear" END
SET #CalMoYear = CAST(CONVERT(NVARCHAR, #CalYear) + '-' + CONVERT(NVARCHAR, #CalMonth) + '-' + CONVERT(NVARCHAR,1) AS DATETIME)
--our fiscal year is not the same as the calendar year
--e.g. FiscalPeriod = 1 and FiscalYear = 2016 will be October 2015
SELECT SUM (CASE WHEN #CalMoYear BETWEEN DATEADD(m, -36, GETDATE()-day(GETDATE()-1)) AND DATEADD(m, -35, GETDATE()-day (GETDATE()-1))-1 THEN"InvenFiscPerHistTable"."QOH" * "InvenTable"."UnitCost" ELSE NULL END) AS "36"
,SUM (CASE WHEN #CalMoYear BETWEEN DATEADD(m, -35, GETDATE()-day(GETDATE()-1)) AND DATEADD(m, -34, GETDATE()-day (GETDATE()-1))-1 THEN"InvenFiscPerHistTable"."QOH" * "InvenTable"."UnitCost" ELSE NULL END) AS "35"
,SUM (CASE WHEN #CalMoYear BETWEEN DATEADD(m, -34, GETDATE()-day(GETDATE()-1)) AND DATEADD(m, -33, GETDATE()-day (GETDATE()-1))-1 THEN"InvenFiscPerHistTable"."QOH" * "InvenTable"."UnitCost" ELSE NULL END) AS "34"
--and so on until I have 36 months of history up through last month
FROM "InvenTable"
INNER JOIN "SKUTable" ON "InvenTable"."SKUKey" = "SKUTable"."SKUKey"
INNER JOIN "InvenFiscPerHistTable" ON ("InvenTable"."SKUKey" = "InvenFiscPerHistTable"."SKUKey")
AND ("InvenTable"."WarehouseKey" = "InvenFiscPerHistTable"."WarehouseKey")
INNER JOIN "SKUClassTable" "SKUClassTable" ON "SKUTable"."ICKey" = "SKUClassTable"."ICKey"
WHERE "SKUClassTable"."ItemClassName" IN (
'105-03'
,'105-04'
,'105-05'
,'105-06'
,'150-01'
)
I played around a bit with your query and think it can be rewritten and simplified (in my opinion) to the query below. The only thing you need to do is add more items in the pivot part at the end to get more columns.
The logic is that it calculates the difference in months between the first day of the current month and the date that is created from the FiscalYear and FiscalPeriod (according to your rules).
I believe it should work, unless I missed something vital, but without any test data there's of course a fair amount of guess work involved ;-)
Please give it a try and if it doesn't work I'll remove my answer.
I formatted it a bit less compact than it could be to make it easier to follow.
;WITH CTE AS
(
SELECT
SKUKey, WarehouseKey, FiscalPeriod, FiscalYear, QOH,
diff = DATEDIFF
(
month,
CASE WHEN FiscalPeriod IN (1,2,3)
THEN
CAST(FiscalYear + 1 AS CHAR(4))
+ '-' + CAST(FiscalPeriod + 9 AS VARCHAR(2))
+ '-' + CAST(1 AS CHAR(1))
ELSE
CAST(FiscalYear AS CHAR(4))
+ '-' + CAST(FiscalPeriod - 3 AS VARCHAR(2))
+ '-' + CAST(1 AS CHAR(1))
END,
DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0)
)
FROM InvenFiscPerHistTable
)
SELECT * FROM
(
SELECT diff, QOH * UnitCost as TotalCost
FROM InvenTable i
INNER JOIN SKUTable s ON i.SKUKey = s.SKUKey
INNER JOIN cte ON (i.SKUKey = cte.SKUKey) AND (i.WarehouseKey = cte.WarehouseKey)
INNER JOIN SKUClassTable sc ON s.ICKey = sc.ICKey
WHERE sc.ItemClassName IN ('105-03','105-04','105-05','105-06','150-01')
) A
PIVOT ( SUM(TotalCost) FOR diff IN ([36],[35],[2],[1]) ) p -- add more columns here
Using MSSQL 2005.
i have a table that counts stats - and the data is stored daily.
what i would like to do - is display a table of data - where the information is grouped by month.
sample data:
id | clickDate | clicksEmail
-------------------------------------
1 10/11/2013 2
2 09/11/2013 1
3 05/11/2013 4
4 30/10/2013 4
this is what i have now:
SELECT datepart(m,clickDate), sum([clicksEmail]) TotalWeb
FROM tblCompanyClicks A WHERE companyID = 1129
GROUP BY datepart(m,clickDate)
ORDER BY datepart(m,clickDate) DESC
which works great. just that i would also like to display the year - not just the month.
but as soon as i add the year into the SQL, its ruins the aggregate function. I tried using a sub select, but that too didnt seem to work.
This is what i would like displayed:
month & year | Summary
-------------------------------
Nov 2013 | 7
Oct 2013 | 4
Assistance appreciated!
Thanks!
Try grouping like :
SELECT CONVERT(VARCHAR(3), clickDate, 0) + ' ' + DATENAME(YEAR, clickDate),
sum([clicksEmail]) TotalWeb
FROM tblCompanyClicks A WHERE companyID = 1129
GROUP BY CONVERT(VARCHAR(3), clickDate, 0) + ' ' + DATENAME(YEAR, clickDate)
ORDER BY CONVERT(VARCHAR(3), clickDate, 0) + ' ' + DATENAME(YEAR, clickDate) DESC
Another way is :
SELECT SUBSTRING(CONVERT(VARCHAR(20), clickDate,106),3,20),
sum([clicksEmail]) TotalWeb
FROM tblCompanyClicks A WHERE companyID = 1129
GROUP BY SUBSTRING(CONVERT(VARCHAR(20), clickDate,106),3,20)
ORDER BY SUBSTRING(CONVERT(VARCHAR(20), clickDate,106),3,20) DESC
For seperate month and year columns you can user DATEPART() function like below :
SELECT DATEPART(YEAR, clickDate) [Year],
DATEPART(MONTH, clickDate) [Month],
sum([clicksEmail]) TotalWeb
FROM tblCompanyClicks A WHERE companyID = 1129
GROUP BY DATEPART(YEAR, clickDate),
DATEPART(MONTH, clickDate)
ORDER BY DATEPART(YEAR, clickDate) DESC,
DATEPART(MONTH, clickDate) DESC
SELECT DATENAME(month,clickDate) + ' ' +
CONVERT(VARCHAR(4),DATEPART(year,clickDate)),
SUM([clicksEmail]) TotalWeb
FROM tblCompanyClicks A
WHERE companyID = 1129
GROUP BY DATENAME(month,clickDate) + ' ' +
CONVERT(VARCHAR(4),DATEPART(year,clickDate))
ORDER BY DATENAME(month,clickDate) + ' ' +
CONVERT(VARCHAR(4),DATEPART(year,clickDate)) DESC
I have an SQL query something along the lines of:
SELECT CONVERT(varchar, DATEPART(month, titlStreaming)) + '/' + CONVERT(varchar, DATEPART(day, titlStreaming)) + '/' + CONVERT(varchar, DATEPART(year, titlStreaming)) AS [Day],
COUNT(titlTitleID) AS Total
FROM Title
GROUP BY DATEPART(year, titlStreaming), DATEPART(month, titlStreaming), DATEPART(day, titlStreaming)
ORDER BY DATEPART(year, titlStreaming) DESC, DATEPART(month, titlStreaming) DESC, DATEPART(day, titlStreaming) DESC
That generally returns a table like:
Day | Total
--------------------
4/23/2013 | 2
...
NULL | 14234
What I would like to do is filter out the row that has a NULL value from returning.
Because Day is a computed column obviously I cannot simply do a WHERE Day IS NOT NULL.
I'll admit my knowledge of SQL is quiet lacking so any help or suggestions would be appreciated.
as far as all dateparts depend on titlStreaming a where condition on titlStreaming should be enough.
....
From Title
where titlStreaming is not null
Group by ....
You can use a subquery:
select *
from (SELECT CONVERT(varchar, DATEPART(month, titlStreaming)) + '/' + CONVERT(varchar, DATEPART(day, titlStreaming)) + '/' + CONVERT(varchar, DATEPART(year, titlStreaming)) AS [Day],
COUNT(titlTitleID) AS Total
FROM Title
GROUP BY DATEPART(year, titlStreaming), DATEPART(month, titlStreaming), DATEPART(day, titlStreaming)
) t
where [day] is not null
ORDER BY [day] DESC
I need to select the last 12 months of rolling demand from a table that contains the following fields:
Item,
Year,
Month,
Demand Qty
I have tried the following:
Select Item, [Year], [Month],[Demand QTY]
FROM [table1]
Where
(
[Year] >= Year(getdate())-'1'
and [Month] >= Month(getdate())
)
and
(
[Year] < year(getdate())+'1'
and [Month] <= month(getdate())
)
but I am only getting the records for last year and this year of the current month.
Item Year Month Demand Qty
CD051 2011 3 8800
CD051 2012 3 0
I'm still a rookie so I could be making obvious mistakes. Could someone please help me?
Try:
Select Item, [Year], [Month],[Demand QTY]
FROM [table1]
Where ( [Year] = Year(getdate())-'1' and [Month] >= Month(getdate()) ) or
( [Year] = year(getdate()) and [Month] <= month(getdate()) )
The best way to do this:
Select * from TableName where (([Year] * 100) + [Month]) >= ((Year(DateAdd(mm, -12, GetDate())) * 100) + (Month(DateAdd(mm, -12, GetDate()))))
This will only give you between 12 months ago and today
Select * from TableName where (([Year] * 100) + [Month]) between ((Year(DateAdd(mm, -12, GetDate())) * 100) + (Month(DateAdd(mm, -12, GetDate())))) and (Year(GetDate()) * 100 + Month(GetDate()))
For an average, you should be able to add
Select [Year], [Month], Avg([Demand QTY]) AvgDemand from TableName where (([Year] * 100) + [Month]) between ((Year(DateAdd(mm, -12, GetDate())) * 100) + (Month(DateAdd(mm, -12, GetDate())))) and (Year(GetDate()) * 100 + Month(GetDate()))
Group by [Year], [Month]
Just remember that if you have other columns in your query that would make the row unique, you Avg wont give you what you expect
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