Matt C
Matt C

Reputation: 903

Querying Counts on Field Values in a Single Table

I have a single product table with multiple fields which contain user evaluations of various attributes:

product  | attr_1_eval   | attr_2_eval   | attr_3_eval
ABC      | Correct       | Incorrect     | Null
DEF      | Incorrect     | Null          | Null
XYZ      | Undetermined  | Null          | Incorrect
123      | Null          | Undetermined  | Correct
456      | Incorrect     | Correct       | Correct

I need to write a query which totals up those attribute evaluations across all products (where not null):

evaluation  | correct   | incorrect   | undetermined
attr_1      | 1         | 2           | 1
attr_2      | 1         | 1           | 1
attr_3      | 2         | 1           | 0

This SQL gets me part way there:

SELECT 
SUM(CASE WHEN attr_1_eval = 'Correct' then 1 else 0 END) AS correct,
SUM(CASE WHEN attr_1_eval = 'Incorrect' then 1 else 0 END) AS incorrect,
SUM(CASE WHEN attr_1_eval = 'Undetermined' then 1 else 0 END) AS undetermined,
SUM(CASE WHEN attr_2_eval = 'Correct' then 1 else 0 END) AS correct,
...
FROM product

But it doesn't group attr_1, attr_2.. by rows with error counts in the columns (as in the desired result set above). I'm using Postgres but help in any flavor of SQL would be most welcome.

Upvotes: 1

Views: 269

Answers (2)

Hambone
Hambone

Reputation: 16377

It's a little brute force, and I hate the fact that it scans the table three times, but this does appear to get the desired output. I'm sorry I don't know PostGres, but this should work in Oracle:

select
  Attribute_name,
  Sum (correct) as Correct,
  sum (incorrect) as Incorrect,
  sum (undetermined) as Undetermined
from
  (
  select
    'attr_1' as Attribute_Name,
    decode (attr_1_eval, 'Correct', 1, 0) as correct,
    decode (attr_1_eval, 'Incorrect', 1, 0) as incorrect,
    decode (attr_1_eval, 'Undetermined', 1, 0) as undetermined
  from product
  union all
  select
    'attr_2',
    decode (attr_2_eval, 'Correct', 1, 0),
    decode (attr_2_eval, 'Incorrect', 1, 0),
    decode (attr_2_eval, 'Undetermined', 1, 0)
  from product
  union all
  select
    'attr_3',
    decode (attr_3_eval, 'Correct', 1, 0),
    decode (attr_3_eval, 'Incorrect', 1, 0),
    decode (attr_3_eval, 'Undetermined', 1, 0)
  from product
)
group by Attribute_Name

Upvotes: 0

Matt Dodge
Matt Dodge

Reputation: 11142

Could you do 3 unions?

SELECT 
  'attr_1' AS evaluation,
  SUM(CASE WHEN attr_1_eval = 'Correct' then 1 else 0 END) AS correct,
  SUM(CASE WHEN attr_1_eval = 'Incorrect' then 1 else 0 END) AS incorrect,
  SUM(CASE WHEN attr_1_eval = 'Undetermined' then 1 else 0 END) AS undetermined
FROM product
UNION
SELECT 
  'attr_2' AS evaluation,
  SUM(CASE WHEN attr_2_eval = 'Correct' then 1 else 0 END) AS correct,
  SUM(CASE WHEN attr_2_eval = 'Incorrect' then 1 else 0 END) AS incorrect,
  SUM(CASE WHEN attr_2_eval = 'Undetermined' then 1 else 0 END) AS undetermined
FROM product
UNION
SELECT 
  'attr_3' AS evaluation,
  SUM(CASE WHEN attr_3_eval = 'Correct' then 1 else 0 END) AS correct,
  SUM(CASE WHEN attr_3_eval = 'Incorrect' then 1 else 0 END) AS incorrect,
  SUM(CASE WHEN attr_3_eval = 'Undetermined' then 1 else 0 END) AS undetermined
FROM product

It's not the most elegant/efficient solution probably but it should get what you want

Upvotes: 1

Related Questions