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

根据地址优先级从多地址中为员工选取唯一地址的SQL问题

解决员工地址优先级筛选问题

我来帮你搞定这个问题~先说说你原来的SQL为啥不行:它的case语句完全没起到优先级筛选的作用,只是在判断地址类型等于自身,相当于没加这个条件,所以会返回该员工所有有效地址,而不是按优先级选出唯一的那条;而且关联表后没做按员工分组取最高优先级地址的处理,结果肯定会有多条记录,不符合你“每个员工唯一地址”的需求。

下面给你两种可行的解决方案,你可以根据自己用的数据库(比如MySQL 8+、SQL Server、PostgreSQL等)选合适的:

方案一:窗口函数法(支持窗口函数的数据库)

这个方法简洁直观,先给地址按优先级打分,再用窗口函数给每个员工的地址排序,取排序第一的那条:

WITH EmpAddressWithPriority AS (
    SELECT 
        e.Id AS EmpId,
        e.Name,
        a.AddressId,
        a.AddressType,
        -- 给地址类型分配优先级分数:a最高(3分),其次c(2分),最后b(1分)
        CASE a.AddressType
            WHEN 'a' THEN 3
            WHEN 'c' THEN 2
            WHEN 'b' THEN 1
            ELSE 0
        END AS PriorityScore,
        -- 按员工分组,按优先级分数降序排序,每个员工的地址会得到1、2、3...的序号
        ROW_NUMBER() OVER (PARTITION BY e.Id ORDER BY 
            CASE a.AddressType
                WHEN 'a' THEN 3
                WHEN 'c' THEN 2
                WHEN 'b' THEN 1
                ELSE 0
            END DESC) AS RowNum
    FROM Emp e
    INNER JOIN EmpAddress ea ON e.Id = ea.EmpId
    INNER JOIN Address a ON a.AddressId = ea.AddressId
    WHERE a.AddressType IS NOT NULL
)
SELECT EmpId, Name, AddressId, AddressType
FROM EmpAddressWithPriority
WHERE RowNum = 1; -- 只取每个员工优先级最高的那条地址

方案二:子查询筛选法(兼容老版本数据库,如MySQL 5.x)

如果你的数据库不支持窗口函数,可以用子查询来筛选每个员工的最高优先级地址:

SELECT 
    e.Id AS EmpId,
    e.Name,
    a.AddressId,
    a.AddressType
FROM Emp e
INNER JOIN EmpAddress ea ON e.Id = ea.EmpId
INNER JOIN Address a ON a.AddressId = ea.AddressId
WHERE a.AddressType IS NOT NULL
AND (
    -- 逻辑:优先选a;没有a时选c;没有a和c时选b
    a.AddressType = 'a'
    OR (
        a.AddressType = 'c'
        AND NOT EXISTS (SELECT 1 FROM EmpAddress ea2 
                        INNER JOIN Address a2 ON ea2.AddressId = a2.AddressId
                        WHERE ea2.EmpId = e.Id AND a2.AddressType = 'a')
    )
    OR (
        a.AddressType = 'b'
        AND NOT EXISTS (SELECT 1 FROM EmpAddress ea2 
                        INNER JOIN Address a2 ON ea2.AddressId = a2.AddressId
                        WHERE ea2.EmpId = e.Id AND a2.AddressType IN ('a','c'))
    )
)
GROUP BY e.Id, e.Name, a.AddressId, a.AddressType; -- 确保每个员工只返回一条记录

测试你的样本数据

用你提供的样本数据测试的话,员工ID=1有a、b、c三个地址,两种方案都会返回地址类型为a的记录;如果某个员工只有b地址,就会返回b;如果有c和b但没有a,就会返回c,完全符合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:11:56