SQL同列条件筛选:优先取statusid=1无则取2的优化方案咨询
嘿,这个需求其实是很常见的按组优先级筛选场景,用Union加临时表虽然能跑,但确实有点繁琐。给你分享几个更简洁高效的SQL实现方案,适配不同的数据库环境:
方案一:窗口函数(推荐,现代数据库通用)
这是最直观也最灵活的方案,支持MySQL 8+、PostgreSQL、SQL Server、Oracle等绝大多数现代数据库。核心思路是给每个projectid分组,按statusid的优先级(1 > 2)排序,然后取每组的第一条记录。
SELECT id, projectid, statusid FROM ( SELECT id, projectid, statusid, -- 按项目分组,statusid越小优先级越高,给每条记录编号 ROW_NUMBER() OVER (PARTITION BY projectid ORDER BY statusid ASC) AS row_rank FROM your_table_name -- 替换成你的实际表名 ) ranked_data WHERE row_rank = 1;
说明:
PARTITION BY projectid:把数据按项目ID分成独立的组ORDER BY statusid ASC:让statusid=1的记录排在同组的最前面ROW_NUMBER():给每组内的记录按顺序编号,取编号为1的就是我们要的优先级最高的记录
方案二:NOT EXISTS子查询(兼容老版本数据库)
如果你的数据库不支持窗口函数(比如MySQL 5.x),可以用这个兼容性更好的方案。思路是:先筛选所有statusid=1的记录,再补充那些statusid=2且对应项目没有statusid=1的记录。
SELECT id, projectid, statusid FROM your_table_name t1 WHERE statusid = 1 OR ( statusid = 2 AND NOT EXISTS ( -- 检查同项目是否存在statusid=1的记录 SELECT 1 FROM your_table_name t2 WHERE t2.projectid = t1.projectid AND t2.statusid = 1 ) );
方案三:GROUP BY + 关联查询(适用于数据规整的场景)
如果每个projectid对应的每个statusid最多只有一条记录(像你给出的示例数据这样),可以用分组取最小statusid再关联原表的方式:
SELECT t1.id, t1.projectid, t1.statusid FROM your_table_name t1 INNER JOIN ( -- 先找到每个项目的最小statusid(也就是优先级最高的状态) SELECT projectid, MIN(statusid) AS preferred_status FROM your_table_name GROUP BY projectid ) t2 ON t1.projectid = t2.projectid AND t1.statusid = t2.preferred_status;
这些方案都能替代你之前的Union+临时表写法,执行效率和可读性都会更好,你可以根据自己的数据库版本和数据情况选择合适的方案~
内容的提问来源于stack exchange,提问作者usr5860
相关产品推荐
相关产品推荐

