I have a stored procedure:
ALTER PROCEDURE GetReportData
AS
BEGIN
SELECT
LOC.SubCompanyNameVN,
LOC.BranchName,
COUNT(LOC.BranchCode) as Total,
----------- Not Processed Yet
SUM (CASE WHEN SS.Status IN (5, 6) THEN 1 ELSE 0 END) AS CountNotProcessedYet,
----------- Processing
SUM (CASE WHEN SS.Status IN (3) THEN 1 ELSE 0 END) AS CountProcessing
FROM
DBO.WorkingSession AS SS
JOIN
DBO.Location AS LOC ON SS.LocationID = LOC.LocationID
AND SS.BranchCode = LOC.BranchCode
JOIN
DBO.Status AS ST ON SS.Status = ST.ID
GROUP BY
LOC.SubCompanyNameVN, LOC.BranchName
ORDER BY
LOC.SubCompanyNameVN
END
The result:
SubCompanyNameVN | BranchName | Total | CountNotProcessedYet | CountProcessing |
---|---|---|---|---|
Vùng 1 | HNI_01 | 5 | 3 | 2 |
Vùng 1 | HNI_02 | 15 | 5 | 10 |
Vùng 1 | HNI_07 | 12 | 6 | 6 |
Vùng 2 | HCM_01 | 86 | 50 | 36 |
Vùng 2 | HCM_03 | 35 | 17 | 18 |
But now I expect my result to be:
SubCompanyOrBranchName | Total | CountNotProcessedYet | CountProcessing |
---|---|---|---|
Vùng 1 | 32 | 14 | 18 |
HNI_01 | 5 | 3 | 2 |
HNI_02 | 15 | 5 | 10 |
HNI_07 | 12 | 6 | 6 |
Vùng 2 | 121 | 67 | 54 |
HCM_01 | 86 | 50 | 36 |
HCM_03 | 35 | 17 | 18 |
How can I group the results by column SubCompanyNameVN (Group By SubCompanyNameVN) to calculate the total like the above table? I have researched and I think I can solve it with ROLLUP but I am confused about it.
CodePudding user response:
Use cte
and union all
with group by
With cte AS (
SELECT
LOC.SubCompanyNameVN,
LOC.BranchName,
COUNT(LOC.BranchCode) as Total,
----------- Not Processed Yet
SUM (CASE WHEN SS.Status IN (5, 6) THEN 1 ELSE 0 END) AS CountNotProcessedYet,
----------- Processing
SUM (CASE WHEN SS.Status IN (3) THEN 1 ELSE 0 END) AS CountProcessing,
ROW_NUMBER() OVER(PARTITION BY LOC.SubCompanyNameVN ORDER BY LOC.SubCompanyNameVN) AS seq
FROM
DBO.WorkingSession AS SS
JOIN
DBO.Location AS LOC ON SS.LocationID = LOC.LocationID
AND SS.BranchCode = LOC.BranchCode
JOIN
DBO.Status AS ST ON SS.Status = ST.ID
GROUP BY
LOC.SubCompanyNameVN, LOC.BranchName)
select SubCompanyNameVN,Total,CountNotProcessedYet,CountProcessing
from
(select SubCompanyNameVN,
sum(Total) As Total,
sum(CountNotProcessedYet) As CountNotProcessedYet,
sum(CountProcessing) As CountProcessing,
dense_rank()over(order by SubCompanyNameVN) As rnk
from cte
group by SubCompanyNameVN
union all
select BranchName,
Total,
CountNotProcessedYet,
CountProcessing,
dense_rank()over(order by SubCompanyNameVN) As rnk
from cte) T
order by rnk,SubCompanyNameVN desc
Demo in db<>fiddle
CodePudding user response:
I found the solution finally by using ROLLUP
, here is what I need:
SELECT
(CASE
WHEN
BranchName is NULL
THEN SubCompanyNameVN ELSE BranchName
END) AS SubCompanyOrBranchName,
Total, CountNotProcessedYet, PercentNotProcessedYet, CountProcessing, PercentProcessing,
CountProcessedIn5Days, PercentProcessedIn5Days, CountProcessedOver5Days, PercentProcessedOver5Days
FROM
(
SELECT
LOC.SubCompanyNameVN,
LOC.BranchName,
COUNT(LOC.BranchCode) as Total,
----------- Not Processed Yet
SUM (CASE WHEN SS.Status IN (5, 6) THEN 1 ELSE 0 END) AS CountNotProcessedYet,
----------- Processing
SUM (CASE WHEN SS.Status IN (3) THEN 1 ELSE 0 END) AS CountProcessing
FROM DBO.WorkingSession AS SS
JOIN DBO.Location AS LOC ON SS.LocationID = LOC.LocationID AND SS.BranchCode = LOC.BranchCode
JOIN DBO.Status AS ST ON SS.Status = ST.ID
GROUP BY ROLLUP(LOC.SubCompanyNameVN, LOC.BranchName)
ORDER BY LOC.SubCompanyNameVN, LOC.BranchName OFFSET 1 ROWS
) T
CodePudding user response:
As well as ROLLUP
, you can also use GROUPING SETS
, which gives you more flexibility in choosing the exact rollups you want.
It's better to use the
GROUPING()
function rather thanISNULL
, because this tells you if the column was actually grouped, and you can see the difference between that an actualNULL
SELECT
CASE WHEN GROUPING(LOC.BranchName) = 0
THEN LOC.BranchName
ELSE LOC.SubCompanyNameVN
END AS SubCompanyOrBranchName,
COUNT(LOC.BranchCode) as Total,
----------- Not Processed Yet
SUM (CASE WHEN SS.Status IN (5, 6) THEN 1 ELSE 0 END) AS CountNotProcessedYet,
----------- Processing
SUM (CASE WHEN SS.Status IN (3) THEN 1 ELSE 0 END) AS CountProcessing
FROM
DBO.WorkingSession AS SS
JOIN
DBO.Location AS LOC ON SS.LocationID = LOC.LocationID
AND SS.BranchCode = LOC.BranchCode
JOIN
DBO.Status AS ST ON SS.Status = ST.ID
GROUP BY GROUPING SETS (
(LOC.SubCompanyNameVN, LOC.BranchName),
(LOC.SubCompanyNameVN)
)
ORDER BY
LOC.SubCompanyNameVN,
GROUPING(LOC.BranchName) DESC, -- put the totalled rows first
LOC.BranchName;