I have table with columns like Gender, Status.
The table value is something like this
ID | Gender | Status |
---|---|---|
1 | Male | A01 |
2 | Male | |
3 | Female | A02 |
4 | Female | |
5 | Unknown | |
6 | Male | |
7 | Female | |
8 | Unknown |
I want to display
Gender | Status | Count |
---|---|---|
Male | A01 | 1 |
Female | A02 | 1 |
Unknown | 0 |
I tried
SELECT
t3.Gender, t3.Status, COUNT(*) AS count
FROM
(SELECT DISTINCT
t1.Gender, t1.Status
FROM
Consumer AS t1
CROSS JOIN
Consumer AS t2
WHERE
t1.Status <> t2.Status
OR t1.Status <> t2.Status) AS t3
GROUP BY
t3.Gender, t3.Status
The final output something I want to display is Please help on this. Thanks
CodePudding user response:
Since the desired results have now been updated, the solution is now much different.
Try:
SELECT
CASE WHEN GROUPING(Status) = 1 THEN 'Total' ELSE Status END AS Status,
--ISNULL(Status, 'Total') AS Status, -- This would not work is actual Status might be null
COUNT(CASE WHEN Gender = 'Female' THEN 1 END) AS Female,
COUNT(CASE WHEN Gender = 'Male' THEN 1 END) AS Male,
COUNT(CASE WHEN Gender = 'Unknown' THEN 1 END) AS Unknown,
COUNT(*) AS Count
FROM @Consumer
WHERE Status > ''
GROUP BY Status WITH Rollup
ORDER BY GROUPING(Status), Status
The above uses conditional aggregation to get the partial counts. WITH ROLLUP
automatically creates a totals row. The ISNULL()
sets a status label for that row (which would otherwise display as null). lastly, the GROUPING()
in the ORDER BY
places the rollup/total after the detail rows.
See this db<>fiddle.
There are also ways to do this using a pivot table, but the above may be sufficient for your current needs.
CodePudding user response:
You might be overthinking your requirements. Perhaps the following will work:
SELECT Gender, Status, COUNT(*) AS count
FROM Consumer
GROUP BY Gender, Status
ORDER BY Gender, Status
It was not clear what you were expecting in your results for unknown gender. If you need special handling for unknown gender and/or blank status, you can add a WHERE
condition to the above for the normal cases and the UNION ALL
the results with a second query to handle the special cases.
SELECT Gender, Status, COUNT(*) AS count
FROM Consumer
WHERE Gender <> 'Unknown' AND Status > ''
GROUP BY Gender, Status
UNION ALL
SELECT 'Unknown' AS Gender, '' AS Status, COUNT(*) AS count
FROM Consumer
WHERE NOT (Gender <> 'Unknown' AND Status > '')