我可以使用“分组依据”来计算多列吗?

时间:2019-06-17 12:31:47

标签: mysql group-by count

我有一个包含以下列的表:

s, s2, s3  
1, 2,  3  
4  
1, 3  
4, 2,  
2, 1  
3, 4  
4  

我想知道s,s2和s3列中s列中的唯一值出现了多少次。

到目前为止,我有:

$query = "SELECT s, COUNT(*) as count FROM table GROUP BY s";

这会给我:

1 - count 2  
2 - count 1  
3 - count 1  
4 - count 3  

但是我也想计算s2和s3列,所以结果将是:

1 - count 3  
2 - count 3  
3 - count 3  
4 - count 4

有什么主意,我必须如何编辑查询,以便可以通过s列的值对s,s2和s3列进行计数?

亲切的问候,

Arie

2 个答案:

答案 0 :(得分:1)

所有列都需要UNION ALL,然后对其进行计数:

select
  t.s, count(*) counter
from (
  select s from tablename union all
  select s2 from tablename union all
  select s3 from tablename
) t
where t.s is not null
group by t.s

请参见demo
结果:

| s   | counter |
| --- | ------- |
| 1   | 3       |
| 2   | 3       |
| 3   | 3       |
| 4   | 4       |

如果在s2s3列中没有s列中不存在的值,并且您希望将它们排除在外,则代替:

where t.s is not null

使用

where t.s in (select s from tablename)

答案 1 :(得分:0)

@forpas答案是一个很好的答案。但是,您应该考虑两件事。

  1. 由于使用union,查询将随着数据大小的增加而变慢。
  2. 如果输入如下:
s, s2, s3  
1, 2,  3  
4  
1, 3  
4, 2,  
2, 1  
3, 4  
4     5

提供的查询结果将是:

| s   | counter |
| --- | ------- |
| 1   | 3       |
| 2   | 3       |
| 3   | 3       |
| 4   | 4       |
| 5   | 1       |

在s列中不应该保留与5相同的值。

为了解决以上两个问题,我提出了使用JOIN代替UNION的方法:

SELECT t3.s, IF(t3.s = t4.s3, cnt1 + 2, cnt1 + 1) as counter FROM 
    (SELECT *, count(*) AS cnt1 FROM 
        (SELECT s from table) AS t1 
        LEFT JOIN 
        (SELECT s2 FROM table) AS t2 
        ON t1.s = t2.s2 GROUP BY t1.s
    ) AS t3 
    LEFT JOIN 
    (SELECT s3 FROM table) AS t4 
    ON t3.s = t4.s3 
ORDER BY t3.s

查询可能看起来有些冗长和复杂,但是当您研究逻辑时,它确实很简单。

第1步
我在这里所做的是从s列到s2进行左连接并计算结果,因此它将使您的数量比总数量少1个,因为它将使关系从左到右。

第2步
然后,我从s到s3进行了左连接,如果找到关系,则仅将步骤1的计数增加1。

第3步
最终,我将计数增加了1,以便我们可以将关系的数量转换为实体的数量。

我希望这是有道理的