I'm trying to create a query which will put some rows in multiple groups. I'm doing this by generating an array that contains both categories I want to group by.
Here's my query so far (slightly simplified to remove extraneous details but substantially similar to avoid the risk of erroneous changes):
SELECT
case when s.compliant then true else false end as "Compliant",
(consequences ->> 'Face Covering or Respirator'='Required' ) as "Masked",
case
when (consequences ->> 'Face Covering or Respirator'='Required') and s.compliant
then '{"Masked","Compliant"}'
when (consequences->>'Face Covering or Respirator'='Required') then '{"Masked"}'
when s.compliant then '{"Compliant"}'
else '{"Non-compliant"}'
end::text[] as "Category",
COUNT(*) AS "Total"
FROM employees
LEFT JOIN surveys s ON s.uid = employees.uid
GROUP BY s.compliant, "Category", "Masked"
Basically, I want 3 totals in the Totals column, even though these groups are not mutually exclusive:
- those who are compliant (whether they must wear a mask or not!)
- those who must wear a mask and are compliant (all of these people are also in the total for # 1)
- those who are non-compliant
Right now my results are
| Compliant | Masked | Category | Total |
|----------------------------------------------------------------------------|
| true | | {Compliant} | 2 |
| true | true | {Masked,Compliant} | 10 |
| false | | {Non-compliant} | 63,204 |
But I want to group by Array ITEMS instead of ARRAYS, like so:
| Compliant | Masked | Category | Total |
|----------------------------------------------------------------------------|
| true | | Compliant | 12 |
| true | true | Masked | 10 |
| false | | Non-compliant | 63,204 |
(If the data doesn't seem to make sense: a person can be compliant with the policy either by getting jabbed or by agreeing to wear a mask, the only options on the survey. Anyone who has not yet taken the survey is considered non-compliant.)
Note the different total for compliant. How can I get the second result set instead of the first?
surveys ashould besurveys s. Show table definitions (CREATE TABLEstatements), your Postgres version and some sample data. – Erwin Brandstetter Nov 04 '21 at 21:12e.consequencesors.consequences? 1:n or 1:1? Are we counting surveys or unique employees? – Erwin Brandstetter Nov 04 '21 at 21:36s.consequencesis a JSONB field with consequences of the answers to the survey, in this case potentially the requirement to wear a mask. There should never be more than one survey per employee, but there can easily be zero. The case statementcase when s.compliant then true else false end as "Compliant"handles the situation where there is no survey yet, to returnfalsefor compliance. – iconoclast Nov 05 '21 at 18:35CREATE TABLEstatement is the source of truth. – Erwin Brandstetter Nov 05 '21 at 18:56