MySQL完全加入COUNTs和GROUP BY

时间:2016-01-27 13:34:59

标签: mysql

我有一张这样的表:

| id | col1     | col2     | col3  | valid |
| 1  | apple    |          |       | 1     |
| 2  | lemon    | apple    |       | 1     |
| 3  | lemon    | pear     |       | 1     |
| 4  | carrot   | apple    |       | 1     |
| 5  | potatoes | tomatoes | apple | 1     |
| 6  | banana   |          |       | 0     |
| 6  | banana   |          |       | 1     |

我需要创建一个MySQL查询,它返回每列中每个条目的计数。理想情况如下:

| apple    | 1    | 2    | 1
| carrot   | 1    | null | null
| lemon    | 2    | null | null
| pear     | null | 1    | null
| potatoes | 1    | null | null
| tomatoes | null | 1    | null
| banana   | 1    | null | null

格式可能不同,我的结果应显示在某些列中出现多少次值。

应该只使用一个查询,我不能使用任何其他语言,任何其他子结果等....,只是:

    (one query)
`input` -> `output`.

我最好的尝试是:

SELECT * 
FROM      (SELECT col1, COUNT(col1) FROM sometable WHERE valid = 1 GROUP BY col1) t1
LEFT JOIN (SELECT col2, COUNT(col2) FROM sometable WHERE valid = 1 GROUP BY col2) t2
    ON t1.col1 = t2.col2
LEFT JOIN (SELECT col3, COUNT(col3) FROM sometable WHERE valid = 1 GROUP BY col3) t3
    ON t1.col1 = t3.col3

但是LEFT JOIN我放了一些行(只有第二或第三列的值),我尝试了几个不同的“join-s”,在MySQL中取得了任何成功

编辑:这些值是动态的,我不知道之前确切的独特可能性

2 个答案:

答案 0 :(得分:1)

你走在正确的轨道上,只需再增加一个子查询,在那里使用union distinct列出3列中的所有可能值,你需要子查询来分别得到每个列的计数:

select f.fruits, m1.fruit_count1, m2.fruit_count2, m3.fruit_count3
from
    (select distinct col1 as fruits from mytable
      union
     select distinct col2 from mytable 
      union
     select distinct col3 from mytable) f
left join
    (select col1, count(col1) as fruit_count1 from mytable where valid=1 group by  col1) m1 on f.fruits=m1.col1
left join
    (select col2, count(col2) as fruit_count2 from mytable where valid=1 group by  col2) m2 on f.fruits=m2.col2
left join
    (select col3, count(col3) as fruit_count3 from mytable where valid=1 group by  col3) m3 on f.fruits=m3.col3;

答案 1 :(得分:1)

select
      item,
      sum( case when whichCol = 1 then 1 else 0 end ) as FoundCol1,
      sum( case when whichCol = 2 then 1 else 0 end ) as FoundCol2,
      sum( case when whichCol = 3 then 1 else 0 end ) as FoundCol3
   from
      ( select col1 as item, 1 as whichCol 
           from YourTable 
           where valid = 1
        union all
        select col2 as item, 2 as whichCol 
           from YourTable 
           where valid = 1
        union all
        select col3 as item, 3 as whichCol 
           from YourTable 
           where valid = 1) allRows
   group by
      item

您需要分别对项目来源的案例和标识符求和。

更有效的方法是预先聚合每列的计数,尤其是在处理大数据集时

select
      item,
      sum( case when whichCol = 1 then TotRecs else 0 end ) as FoundCol1,
      sum( case when whichCol = 2 then TotRecs else 0 end ) as FoundCol2,
      sum( case when whichCol = 3 then TotRecs else 0 end ) as FoundCol3
   from
      ( select col1 as item, max(1) as whichCol, count(*) as TotRecs
           from YourTable 
           group by col1
        union all
        select col2 as item, max(2) as whichCol, count(*) as TotRecs
           from YourTable 
           group by col2
        union all
        select col3 as item, max(3) as whichCol, count(*) as TotRecs
           from YourTable 
           group by col3 ) allRows
   group by
      item