我有一个包含以下列的表:
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
答案 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 |
如果在s2
和s3
列中没有s
列中不存在的值,并且您希望将它们排除在外,则代替:
where t.s is not null
使用
where t.s in (select s from tablename)
答案 1 :(得分:0)
@forpas答案是一个很好的答案。但是,您应该考虑两件事。
union
,查询将随着数据大小的增加而变慢。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,以便我们可以将关系的数量转换为实体的数量。
我希望这是有道理的