Reputation: 1
I've just started learning SQL (specifically SQLite) and I've been playing with this data.
Every Marvel character in this list has rating for each attribute (strength, intelligence, speed, etc.) I want to find how many characters have each attribute as their greatest. For example, how many characters have strength as their greatest attribute?
We can assume that if a character has two or more attributes as their highest, that character will count towards each attribute.
The output I'm expecting is something like:
best_Attribute COUNT(*)
__________________________________
intelligence a
strength b
speed c
durability d
energy_Projection e
fighting_Skills f
Here's my attempt:
SELECT COUNT(*),
CASE
WHEN MAX(intelligence, strength, speed, durability, energy_Projection, fighting_Skills) == intelligence THEN "intelligence"
WHEN MAX(intelligence, strength, speed, durability, energy_Projection, fighting_Skills) == strength THEN "strength"
WHEN MAX(intelligence, strength, speed, durability, energy_Projection, fighting_Skills) == speed THEN "speed"
WHEN MAX(intelligence, strength, speed, durability, energy_Projection, fighting_Skills) == durability THEN "durability"
WHEN MAX(intelligence, strength, speed, durability, energy_Projection, fighting_Skills) == energy_Projection THEN "energy_Projection"
WHEN MAX(intelligence, strength, speed, durability, energy_Projection, fighting_Skills) == fighting_Skills THEN "fighting_Skills"
END as "best_Attribute"
FROM marvels
GROUP BY best_Attribute;
This is ugly, verbose and doesn't even work. Here is the output:
COUNT(*) best_Attribute
__________________________
2 4
3 6
7 7
Is there a (nice) way of getting the desired output?
Upvotes: 0
Views: 49
Reputation: 1269873
Tim's solution is the most performant method -- and how you were approaching the problem. However, another method is to unpivot the data and use aggregation. I just want to offer this as an alternative so you can see different ways of solving the problem in SQL:
with a as (
select name, 'intelligence' as attribute, intelligence as val
from marvels
union all
select name, 'strength' as attribute, strength as val
from marvels
union all
select name, 'speed' as attribute, speed as val
from marvels
union all
select name, 'durability' as attribute, durability as val
from marvels
union all
select name, 'energy_Projection' as attribute, energy_Projection as val
from marvels
union all
select name, 'fighting_Skills' as attribute, fighting_Skills as val
from marvels
)
select a.attribute, count(*) as num_with_max
from a
where a.val = (select max(a2.val) from a a2 where a2.name = a.name)
group by a.attribute;
Upvotes: 1
Reputation: 521314
I'm not sure if you need your exact suggested output. I can offer the following query, which would report the attribute counts over the entire table as separate columns.
SELECT
COUNT(CASE WHEN MAX(intelligence, strength, speed, durability, energy_Projection,
fighting_Skills) = intelligence THEN 1 END) AS intelligence_count
COUNT(CASE WHEN MAX(intelligence, strength, speed, durability, energy_Projection,
fighting_Skills) = strength THEN 1 END) AS strength_count
COUNT(CASE WHEN MAX(intelligence, strength, speed, durability, energy_Projection,
fighting_Skills) = speed THEN 1 END) AS speed_count
COUNT(CASE WHEN MAX(intelligence, strength, speed, durability, energy_Projection,
fighting_Skills) = durability THEN 1 END) AS durability_count
COUNT(CASE WHEN MAX(intelligence, strength, speed, durability, energy_Projection,
fighting_Skills) = energy_Projection THEN 1 END) AS energy_Projection_count
COUNT(CASE WHEN MAX(intelligence, strength, speed, durability, energy_Projection,
fighting_Skills) = fighting_Skills THEN 1 END) AS fighting_Skills_count
FROM marvels;
Note that you don't need to use GROUP BY
here if you want totals over the entire table.
Upvotes: 2