MySQL从组合的多个字段中获取COUNT

时间:2013-02-06 14:01:02

标签: mysql self-join union-all

说我有一张桌子:

user_id    parent_id    lev1    lev2   lev3    lev4
1          0            0       0      0       0
2          1            1       0      0       0
3          1            1       0      0       0
4          2            2       1      0       0
5          4            4       2      1       0
6          4            4       2      1       0
7          5            5       4      2       1

基本上,这是为了跟踪父子关系,我想知道父母有多少孩子。以下是我想要的输出:

parent_id     children
1             5
2             4
3             0
4             3
5             1
6             0
7             0

我想计算合并的lev1,lev2,lev3和lev4字段来计算这些字段中所有ID的总数。

我读到了UNION ALL,但我似乎无法弄清楚它是如何运作的。我正想着一个自我加入的UNION ALL?

2 个答案:

答案 0 :(得分:3)

对于每个LEFT JOIN列,您需要针对子查询levN,该列返回该列的不同级别和计数。然后,他们都会加起来并加入user_id

SELECT
  DISTINCT
  user_id,
  /* COALESCE() is needed so NULLs don't ruin the calculation */
  COALESCE(l1count, 0) +
  COALESCE(l2count, 0) +
  COALESCE(l3count, 0) +
  COALESCE(l4count, 0) AS children
FROM
  yourtable
  /* a left join individually against each of the `levN` columns to get the count per value of each */
  LEFT JOIN (SELECT lev1, COUNT(*) AS l1count FROM yourtable GROUP BY lev1) l1 ON yourtable.user_id = l1.lev1
  LEFT JOIN (SELECT lev2, COUNT(*) AS l2count FROM yourtable GROUP BY lev2) l2 ON yourtable.user_id = l2.lev2
  LEFT JOIN (SELECT lev3, COUNT(*) AS l3count FROM yourtable GROUP BY lev3) l3 ON yourtable.user_id = l3.lev3
  LEFT JOIN (SELECT lev4, COUNT(*) AS l4count FROM yourtable GROUP BY lev4) l4 ON yourtable.user_id = l4.lev4

http://sqlfiddle.com/#!2/214a8/16

答案 1 :(得分:2)

我可以在那里部分到达你,除了我没有显示零数的任何东西。 (另外,正如@RaphaëlAlthaus指出的那样,父母1在你的数据中有6个不算数5)。

sqlite> .schema
CREATE TABLE tmp (
user int,
parent int,
l1 int,
l2 int,
l3 int,
l4 int
);
sqlite> select * from tmp;
1,0,0,0,0,0
2,1,1,0,0,0
3,1,1,0,0,0
4,2,2,1,0,0
5,4,4,2,1,0
6,4,4,2,1,0
7,5,5,4,2,1
sqlite> select who,count(who) from
   ...>   (select l1 as who from tmp union all
   ...>    select l2 as who from tmp union all
   ...>    select l3 as who from tmp union all
   ...>    select l4 as who from tmp)
   ...> where who <> 0
   ...> group by who;
1,6
2,4
4,3
5,1
sqlite>