PHP MySQL:统计分组中未出现在另一表的记录数并排序
解决方案:统计各Block未出现在Table B的记录数
当然可以实现这个需求!我来给你拆解问题并提供具体的SQL实现,完全能满足你生成图表数据的要求。
先明确你的数据与预期
Table A 数据
| pid | block |
|---|---|
| 1 | 1 |
| 2 | 1 |
| 3 | 2 |
| 4 | 3 |
| 5 | 2 |
| 6 | 3 |
Table B 数据
| cid | pid |
|---|---|
| 1 | 1 |
| 2 | 3 |
| 3 | 5 |
你需要的输出
统计每个block下,Table A中pid未出现在Table B的记录数,并且按block排序,结果如下:
| block | total |
|---|---|
| 1 | 1 |
| 2 | 0 |
| 3 | 2 |
具体SQL实现(推荐第一种)
方法1:LEFT JOIN 实现(确保显示所有block,包括total=0的)
这种方法能保证所有block都出现在结果里,哪怕该block下所有记录都在Table B中,完美匹配你的预期输出:
SELECT a.block, COUNT(CASE WHEN b.pid IS NULL THEN 1 END) AS total FROM table_a a LEFT JOIN table_b b ON a.pid = b.pid GROUP BY a.block ORDER BY a.block;
逻辑解释:
- 用
LEFT JOIN关联两张表,关联条件是a.pid = b.pid,这样Table A的所有记录都会保留,匹配不到的Table B字段会显示NULL - 用
CASE WHEN筛选出那些匹配不到(也就是pid不在Table B)的记录,统计它们的数量就是每个block的total - 最后按block分组并排序,直接就能用于图表展示
方法2:NOT EXISTS 写法(需额外处理total=0的block)
如果你的数据库对NOT EXISTS优化更好,可以用这种写法,但要额外处理那些total为0的block,确保它们出现在结果中:
-- 先获取所有存在的block,再关联统计结果 WITH all_blocks AS ( SELECT DISTINCT block FROM table_a ) SELECT ab.block, COALESCE(t.total, 0) AS total FROM all_blocks ab LEFT JOIN ( -- 统计每个block下未出现在Table B的记录数 SELECT a.block, COUNT(*) AS total FROM table_a a WHERE NOT EXISTS ( SELECT 1 FROM table_b b WHERE b.pid = a.pid ) GROUP BY a.block ) t ON ab.block = t.block ORDER BY ab.block;
逻辑解释:
- 先用
WITH子句获取Table A中所有不同的block - 子查询里用
NOT EXISTS找出Table A中pid不在Table B的记录,按block统计数量 - 最后用
LEFT JOIN把所有block和统计结果关联,用COALESCE把NULL转为0,确保每个block都有结果
这两种写法都能完美满足你的需求,你可以根据自己使用的数据库(比如MySQL、PostgreSQL等)选择最顺手的方式,生成的数据直接就能用于图表展示。
内容的提问来源于stack exchange,提问作者pattygeek
相关产品推荐
相关产品推荐

