如何基于非唯一列连接表且不产生冗余结果?(多银行代码关联场景)
解决客户表与银行表关联后出现重复记录的问题
这个场景我碰到过好几次——因为银行表的Code字段不是唯一的,直接关联就会导致同一个客户对应多条银行记录。要实现每个客户只返回一条结果,这里有几个实用的方案:
方案1:用聚合函数筛选唯一银行名称
最简单的方式是通过GROUP BY分组,搭配MIN()或MAX()聚合函数,从重复的银行名称里选任意一个即可。这样每个客户的记录只会保留一条:
SELECT P.Id, P.Name, P.BankCode, MIN(B.Name) AS BankName -- 换成MAX()也能达到同样效果 FROM Customers P JOIN Banks B ON P.BankCode = B.Code GROUP BY P.Id, P.Name, P.BankCode;
比如你的示例数据里,BankCode=2的银行名称是National和National Subsidiary,用MIN()会取到National,用MAX()会取到National Subsidiary,看你需求选就行。
方案2:用窗口函数指定取某一条银行记录
如果想更精准地控制取哪一条银行记录(比如取Id最小的主行),可以用ROW_NUMBER()窗口函数给每个Code下的银行记录编号,然后只取编号为1的那条:
WITH RankedBanks AS ( SELECT Code, Name, -- 按Code分组,给每个组内的记录按Id排序编号 ROW_NUMBER() OVER (PARTITION BY Code ORDER BY Id) AS rn FROM Banks ) SELECT P.Id, P.Name, P.BankCode, RB.Name AS BankName FROM Customers P JOIN RankedBanks RB ON P.BankCode = RB.Code WHERE RB.rn = 1;
这个方法灵活性很高,你可以修改ORDER BY的字段来选择不同的记录,比如按Name排序取第一个,或者按其他业务规则调整。
方案3:先对银行表去重再关联
如果你的数据库支持DISTINCT ON(比如PostgreSQL),可以先对银行表按Code去重,得到每个Code对应唯一的一条记录,再和客户表关联:
SELECT P.Id, P.Name, P.BankCode, B.Name AS BankName FROM Customers P JOIN ( SELECT DISTINCT ON (Code) Code, Name FROM Banks ORDER BY Code, Id -- 这里的排序决定了取哪一条记录 ) B ON P.BankCode = B.Code;
如果是MySQL或SQL Server,你可以用子查询+聚合的方式实现类似的去重效果,核心思路都是先让每个Code只对应一条银行记录,再做关联。
内容的提问来源于stack exchange,提问作者Hamid Siaban
相关产品推荐
相关产品推荐

