I am doing a jasper report to count the statistic of the fruits choices.
I have 2 table, Fruit, Fruit_choices
Table Fruit :
| id | fruit |
|---|---|
| 0 | apple |
| 1 | banana |
| 2 | orange |
Table Fruit_choices :
| id | choice_1 | choice_2 | choice_3 |
|---|---|---|---|
| 0 | 0 | 1 | 2 |
| 1 | 0 | 2 | 1 |
| 2 | 2 | 0 | 1 |
I want to know the sum of the user that select the fruits in choice_1,choice_2,choice_3
My ideal output is like below
| fruit | c1Count | c2Count | c3Count |
|---|---|---|---|
| apple | 2 | 1 | 0 |
| banana | 0 | 1 | 2 |
| orange | 1 | 1 | 1 |
CodePudding user response:
If you have only 3 choice, you can get the result with combination of UNION and Aggregation.
If your number of choices increase, then the query would be more complicated and expensive
SELECT f.FRUIT,SUM(C1COUNT),SUM(C2COUNT),SUM(C3COUNT)
FROM
FRUIT f
JOIN
(
SELECT CHOICE_1 AS FRUIT ,COUNT(1) AS C1COUNT, 0 AS C2COUNT, 0 AS C3COUNT
FROM FRUIT_CHOICES
GROUP BY CHOICE_1
UNION
SELECT CHOICE_2 AS FRUIT,0 AS C1COUNT, COUNT(1) AS C2COUNT, 0 AS C3COUNT
FROM FRUIT_CHOICES
GROUP BY CHOICE_2
UNION
SELECT CHOICE_3 AS FRUIT,0 AS C1COUNT, 0 AS C2COUNT, COUNT(1) AS C3COUNT
FROM FRUIT_CHOICES
GROUP BY CHOICE_3
) c
ON f.ID=c.FRUIT
GROUP BY c.FRUIT
https://dbfiddle.uk/?rdbms=mysql_5.5&fiddle=07dd3ca27d231cfcdfbcbefff7f140f6
Explanation:
We can separate our data for each choice. For example, for CHOICE_1, we can group by it and get count of only CHOICE_1. We have to hardcode 0 for other counts.
SELECT CHOICE_1 AS FRUIT ,COUNT(1) AS C1COUNT, 0 AS C2COUNT, 0 AS C3COUNT
FROM FRUIT_CHOICES
GROUP BY CHOICE_1
This will give you below result.
------- --------- --------- ---------
| FRUIT | C1COUNT | C2COUNT | C3COUNT |
------- --------- --------- ---------
| F0 | 2 | 0 | 0 |
| F2 | 1 | 0 | 0 |
------- --------- --------- ---------
Similarly union for other 2 choices to get below result
------- --------- --------- ---------
| FRUIT | C1COUNT | C2COUNT | C3COUNT |
------- --------- --------- ---------
| F0 | 2 | 0 | 0 |
| F2 | 1 | 0 | 0 |
| F0 | 0 | 1 | 0 |
| F1 | 0 | 1 | 0 |
| F2 | 0 | 1 | 0 |
| F1 | 0 | 0 | 1 |
| F2 | 0 | 0 | 1 |
------- --------- --------- ---------
Now you can group by FRUIT and use SUM to get count of each FRUIT. Then join the final result with FRUIT table to get name of the FRUIT.
CodePudding user response:
I'm using conditional aggregation. No GROUP BY clause is required in this case. If you're interested, try it.
select fruit,c1Count,c2Count,c3Count
from Fruit t1
join
(select 0 as id,
sum(case choice_1 when 0 then 1 else 0 end) as c1Count,
sum(case choice_2 when 0 then 1 else 0 end) as c2Count,
sum(case choice_3 when 0 then 1 else 0 end) as c3Count
from Fruit_choices
union
select 1 ,
sum(case choice_1 when 1 then 1 else 0 end) ,
sum(case choice_2 when 1 then 1 else 0 end) ,
sum(case choice_3 when 1 then 1 else 0 end)
from Fruit_choices
union
select 2 ,
sum(case choice_1 when 2 then 1 else 0 end) ,
sum(case choice_2 when 2 then 1 else 0 end) ,
sum(case choice_3 when 2 then 1 else 0 end)
from Fruit_choices
) t2
using(id)
;
