如何筛选关联Programs不含D、E的ID?SQL实现方案咨询
需求说明
先明确下需求:我们有下面这张数据表,需要筛选出从来没有关联过Programs值为D或E的ID,最终目标ID是6、7、10、11。
数据表如下:
| ID | Location | Programs | School |
|---|---|---|---|
| 1 | ABC | A | 1 |
| 1 | ABC | B | 1 |
| 1 | ABC | C | 1 |
| 1 | ABC | D | 1 |
| 2 | ABC | A | 1 |
| 2 | ABC | B | 1 |
| 2 | ABC | C | 1 |
| 3 | ABC | D | 1 |
| 4 | ABC | A | 1 |
| 4 | ABC | B | 1 |
| 4 | ABC | C | 1 |
| 4 | ABC | D | 1 |
| 5 | ABC | A | 1 |
| 5 | ABC | C | 1 |
| 5 | ABC | D | 1 |
| 6 | ABC | A | 1 |
| 6 | ABC | B | 1 |
| 6 | ABC | C | 1 |
| 7 | ABC | A | 1 |
| 7 | ABC | B | 1 |
| 7 | ABC | C | 1 |
| 8 | ABC | A | 1 |
| 8 | ABC | B | 1 |
| 8 | ABC | C | 1 |
| 8 | ABC | D | 1 |
| 8 | ABC | E | 1 |
| 9 | ABC | B | 1 |
| 9 | ABC | C | 1 |
| 9 | ABC | D | 1 |
| 9 | ABC | E | 1 |
| 10 | ABC | A | 1 |
| 10 | ABC | B | 1 |
| 10 | ABC | C | 1 |
| 11 | ABC | A | 1 |
| 11 | ABC | B | 1 |
实现方案建议
下面给你几种实用的SQL实现方法,适配MySQL、PostgreSQL、SQL Server等大多数主流关系型数据库,你可以根据自己的数据库环境和数据量选择:
方法1:NOT IN子查询(直观易懂)
先找出所有关联过D/E的ID,再排除这些ID:
SELECT DISTINCT ID FROM your_table_name WHERE ID NOT IN ( SELECT DISTINCT ID FROM your_table_name WHERE Programs IN ('D', 'E') );
小提示:用DISTINCT是为了避免结果里出现重复的ID,毕竟一个ID会对应多条Programs记录。
方法2:NOT EXISTS子查询(性能更优)
这种方法在处理大数据量时表现更好,因为数据库找到一个D/E记录就会停止检查当前ID,不用遍历所有子记录:
SELECT DISTINCT t1.ID FROM your_table_name t1 WHERE NOT EXISTS ( SELECT 1 FROM your_table_name t2 WHERE t2.ID = t1.ID AND t2.Programs IN ('D', 'E') );
方法3:LEFT JOIN+筛选NULL(逻辑清晰)
通过左连接把有D/E记录的ID关联过来,然后筛选那些没关联上的ID(也就是没有D/E记录的):
SELECT DISTINCT t1.ID FROM your_table_name t1 LEFT JOIN ( SELECT DISTINCT ID FROM your_table_name WHERE Programs IN ('D', 'E') ) t2 ON t1.ID = t2.ID WHERE t2.ID IS NULL;
方法4:聚合函数统计(灵活拓展)
如果以后需要调整筛选条件(比如统计D/E数量小于2的ID),这种方法更容易修改:
SELECT ID FROM your_table_name GROUP BY ID HAVING SUM(CASE WHEN Programs IN ('D', 'E') THEN 1 ELSE 0 END) = 0;
解释:SUM(CASE...)会统计每个ID下D/E的记录数,等于0就说明这个ID从来没关联过D或E,正好符合需求。
内容的提问来源于stack exchange,提问作者Jay2012
相关产品推荐
相关产品推荐

