You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多表关联SQL查询按指定优先级返回唯一结果的需求

按优先级筛选每个ID唯一结果的SQL解决方案

嘿,针对你遇到的这个SQL结果去重+优先级筛选的问题,我整理了两种靠谱的解决方法,一起来看看:

问题回顾

你当前的查询语句是:

SELECT t.id, a.name 
FROM table1 a, table2 t 
WHERE a.id = t.id

执行后得到的重复结果:

id | name
1  | Foo
1  | Bar
2  | Bar

你的需求很明确:每个id只保留一条记录,优先取name为Foo的;如果没有Foo,再取Bar,期望得到的目标结果:

id | name
1  | Foo
2  | Bar

解决方案

方法一:用窗口函数(推荐,通用且高效)

现在大部分主流数据库(MySQL 8+、PostgreSQL、SQL Server等)都支持窗口函数,用ROW_NUMBER()可以轻松实现优先级排序筛选:

WITH ranked_records AS (
    SELECT 
        t.id,
        a.name,
        -- 按优先级给每个id下的记录排序:Foo排1,Bar排2,其他情况排最后
        ROW_NUMBER() OVER (
            PARTITION BY t.id 
            ORDER BY CASE a.name WHEN 'Foo' THEN 1 WHEN 'Bar' THEN 2 ELSE 3 END ASC
        ) AS rank_num
    FROM table1 a
    INNER JOIN table2 t ON a.id = t.id -- 换成显式JOIN,可读性更强
)
SELECT id, name
FROM ranked_records
WHERE rank_num = 1;

💡 这里的逻辑是:

  • PARTITION BY t.id:把数据按id分成一个个小组
  • ORDER BY CASE ...:给每个小组里的记录按你的优先级排序,Foo的序号最小,所以排最前面
  • 最后只取每个小组里序号为1的那条,就是每个id的最高优先级记录

方法二:子查询方案(兼容老版本数据库)

如果你的数据库版本比较旧,不支持窗口函数,可以用子查询来实现:

SELECT 
    DISTINCT t.id,
    CASE
        -- 先检查当前id有没有Foo,有就返回Foo
        WHEN EXISTS (SELECT 1 FROM table1 a WHERE a.id = t.id AND a.name = 'Foo') THEN 'Foo'
        -- 没有Foo就返回Bar
        ELSE 'Bar'
    END AS name
FROM table1 a
JOIN table2 t ON a.id = t.id;

这个方法的思路是对每个id做判断,优先匹配Foo,匹配不到就用Bar,适合不支持窗口函数的场景。

小建议

日常写SQL的时候,尽量用显式JOIN(比如INNER JOIN)代替逗号分隔表名的隐式关联,这样代码的逻辑更清晰,也不容易写错关联条件哦~

内容的提问来源于stack exchange,提问作者java java

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 03:56:26