You need to enable JavaScript to run this app. 使用SQL按分组与条件筛选记录:优先选客户偏好名无则选法定名
优惠活动
大模型
产品
解决方案
定价
更多

使用SQL按分组与条件筛选记录:优先选客户偏好名无则选法定名

实现方案

这个需求属于典型的「分组内按优先级取最高权重记录」场景,下面给几种不同适用场景的实现方式,示例表名统一为customer_names。

方案1:窗口函数法(兼容性最高,支持所有主流新版数据库)

这是最通用的实现方式,MySQL 8.0+、PostgreSQL、SQL Server、Oracle 均支持:

WITH ranked_names AS (
    SELECT 
        *,
        ROW_NUMBER() OVER (
            PARTITION BY ID 
            ORDER BY CASE WHEN TYPE = 'PREF' THEN 1 ELSE 2 END ASC
        ) AS rn
    FROM customer_names
    WHERE TYPE IN ('PREF', 'LEGAL') -- 过滤无关类型的记录,按需开启
)
SELECT ID, TYPE, FIRST, LAST
FROM ranked_names
WHERE rn = 1;

逻辑说明:

  • 用PARTITION BY ID按客户ID分组
  • 每组内通过自定义排序规则给记录加权:PREF类型优先级高排序为1,LEGAL为2,保证同个ID下PREF永远排在LEGAL前面
  • 最后过滤取每组排序第一的记录即可,完全匹配需求逻辑

方案2:关联子查询法(兼容低版本数据库,如MySQL 5.x)

如果你的数据库不支持窗口函数,可以用这种写法:

SELECT t1.*
FROM customer_names t1
LEFT JOIN customer_names t2 
    ON t1.ID = t2.ID 
    AND t2.TYPE = 'PREF'
WHERE 
    (t1.TYPE = 'PREF') 
    OR (t1.TYPE = 'LEGAL' AND t2.ID IS NULL)
GROUP BY t1.ID, t1.TYPE, t1.FIRST, t1.LAST;

逻辑说明:

  • 把同个ID的记录和该ID下的PREF类型记录做左关联
  • 如果当前记录是PREF直接保留
  • 如果当前记录是LEGAL,则判断该ID有没有关联到PREF记录,没有关联到(即t2.ID IS NULL)才保留

方案3:PostgreSQL 专属简化写法

如果你用的是PostgreSQL,可以用DISTINCT ON语法更简洁的实现:

SELECT DISTINCT ON (ID) ID, TYPE, FIRST, LAST
FROM customer_names
WHERE TYPE IN ('PREF', 'LEGAL')
ORDER BY ID, CASE WHEN TYPE = 'PREF' THEN 1 ELSE 2 END ASC;

所有方法测试后都可以输出你给出的期望结果,性能上窗口函数法最优,数据量越大优势越明显。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 09:48:04