CREATE TABLE #foo
(
itemid int,
proddte date,
qty int
);
INSERT #foo(itemid,proddte,qty) VALUES
(1,'20140101',5),(1,'20140102',7),(2,'20150101',10);
-- if it really needs to be a column with the same value
-- in every row, just calculate once and assign it to a variable
DECLARE @sum int = (SELECT SUM(qty) FROM #foo);
SELECT itemid, proddte, GroupedSum = SUM(qty), GrandTotal = @sum
FROM #foo
GROUP BY itemid, proddte;
-- if the grand total can be expressed on its own row,
-- you can use GROUP BY GROUPING SETS:
SELECT itemid, proddte, SUM(qty)
FROM #foo GROUP BY GROUPING SETS((),(itemid,proddte));
-- if that syntax is confusing, you can use a less
-- efficient UNION ALL:
SELECT itemid, proddte, SUM(qty)
FROM #foo GROUP BY itemid,proddte
UNION ALL
SELECT NULL, NULL, SUM(qty)
FROM #foo;
GO
DROP TABLE #foo;
The GROUP BY GROUPING SETS
is is basically a UNION ALL
. The ()
means just take the SUM
regardless of grouping, any other group listed gets aggregated separately. Try GROUP BY GROUPING SETS ((itemid),(itemid,proddte))
to see the difference.
For more details see the documentation:
Using GROUP BY with ROLLUP, CUBE, and GROUPING SETS
As Andriy mentioned, the query above could also be written using:
GROUP BY ROLLUP( (itemid,proddte) )
Note the two columns there are enclosed in an additional pair of parentheses, making them a single unit. Andriy wrote a demo hosted on the Stack Exchange Data Explorer.
Add as many SUM(CASE as you need according selected dates.
SELECT WoPart.PartNumber AS [Part Number]
,Parts.Descript AS [Description]
,SUM(CASE WHEN YEAR(RelDateTime) = 2014
AND DATEPART(QQ, RelDateTime) = 1 THEN Qty ELSE 0 END) AS 'Qtr1/14'
,SUM(CASE WHEN YEAR(RelDateTime) = 2014
AND DATEPART(QQ, RelDateTime) = 2 THEN Qty ELSE 0 END) AS 'Qtr2/14'
,SUM(CASE WHEN YEAR(RelDateTime) = 2014
AND DATEPART(QQ, RelDateTime) = 3 THEN Qty ELSE 0 END) AS 'Qtr3/14'
,SUM(CASE WHEN YEAR(RelDateTime) = 2014
AND DATEPART(QQ, RelDateTime) = 4 THEN Qty ELSE 0 END) AS 'Qtr4/14'
,SUM(CASE WHEN YEAR(RelDateTime) = 2014 THEN Qty ELSE 0 END) AS '2014'
,SUM(CASE WHEN YEAR(RelDateTime) = 2015
AND DATEPART(QQ, RelDateTime) = 1 THEN Qty ELSE 0 END) AS 'Qtr1/15'
,SUM(CASE WHEN YEAR(RelDateTime) = 2015
AND DATEPART(QQ, RelDateTime) = 2 THEN Qty ELSE 0 END) AS 'Qtr2/15'
,SUM(CASE WHEN YEAR(RelDateTime) = 2015
AND DATEPART(QQ, RelDateTime) = 3 THEN Qty ELSE 0 END) AS 'Qtr3/15'
,SUM(CASE WHEN YEAR(RelDateTime) = 2015
AND DATEPART(QQ, RelDateTime) = 4 THEN Qty ELSE 0 END) AS 'Qtr4/15'
,SUM(CASE WHEN YEAR(RelDateTime) = 2015 THEN Qty ELSE 0 END) AS '2015'
,SUM(CASE WHEN YEAR(RelDateTime) = 2016
AND DATEPART(QQ, RelDateTime) = 1 THEN Qty ELSE 0 END) AS 'Qtr1/16'
,SUM(CASE WHEN YEAR(RelDateTime) = 2016
AND DATEPART(QQ, RelDateTime) = 2 THEN Qty ELSE 0 END) AS 'Qtr2/16'
,SUM(CASE WHEN YEAR(RelDateTime) = 2016
AND DATEPART(QQ, RelDateTime) = 3 THEN Qty ELSE 0 END) AS 'Qtr3/16'
,SUM(CASE WHEN YEAR(RelDateTime) = 2016
AND DATEPART(QQ, RelDateTime) = 4 THEN Qty ELSE 0 END) AS 'Qtr4/16'
,SUM(CASE WHEN YEAR(RelDateTime) = 2016 THEN Qty ELSE 0 END) AS '2016'
FROM WoPart
INNER JOIN WorkOrders
ON WorkOrders.RecordID = WoPart.RecordID
INNER JOIN Parts
ON WoPart.PartNumber = Parts.PartNumber
WHERE RelDateTime >= CAST('20140101' AS DATETIME)
AND RelDateTime < CAST('20170101' AS DATETIME)
GROUP BY WoPart.PartNumber, Parts.Descript;
Best Answer
You can use a
GROUP BY GROUPING SETS
over theNULL
setVerified to work with PostgreSQL. SQL Server 2014 and SQL Server 2016.
The docs at PostgreSQL are much better explaining this
Another method of doing this is with a
UNION
,For your query, the first method would look like this..