简体   繁体   中英

SQL query to get count of distinct values of columns in a same table

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

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 or this one with expanded test data.

There are also ways to do this using a pivot table, but the above may be sufficient for your current needs.

select  *
       ,Male + Female + Unknown as count
from    t
pivot(count(id) for gender in(Male, Female, Unknown))p
where status is not null

union all


select  'Total'
       ,count(case when gender = 'Male' then status end)    as Male
       ,count(case when gender = 'Female' then status end)  as Female
       ,count(case when gender = 'Unknown' then status end) as Unknown
       ,count(status) as Total
from   t
Status Male Female Unknown count
A01 1 0 0 1
A02 0 1 0 1
Total 1 1 0 2

Fiddle

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 > '')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM