多对一映射下P_Data关联Address表的不重复主字段显示SQL实现
实现结论与方案
该需求完全可实现,既可以解决原有查询主表字段重复的问题,也能兼容无关联地址的主表记录场景。
核心实现逻辑
你目前编写的内连接查询存在两个明显问题:一是主表字段会随每条关联地址重复展示,二是会直接过滤掉P_Data中没有关联任何地址的记录。方案针对这两个问题做了适配,核心思路为:
- 替换原有内连接为左外连接:保证主表所有记录不丢失,哪怕没有匹配的地址数据
- 引入窗口函数给关联后的结果做分组行号标记:按
Data_Id维度分组,按地址表的主键排序,标记同个主表ID下每一条地址记录的顺序 - 条件化返回主表字段:仅当记录是同个Data_Id下的第一条时,才返回主表的三个字段值,其余关联行的主表字段直接返回空值,满足不重复展示的要求
通用SQL代码
WITH join_result AS ( SELECT pd.Data_Id, pd.First_Name, pd.Last_Name, a.Address_Type, a.address_data, -- 按主表ID分组,生成组内顺序行号 ROW_NUMBER() OVER ( PARTITION BY pd.Data_Id ORDER BY a.ID ASC ) AS group_row_num FROM P_Data pd -- 用左连接保留所有主表记录,哪怕没有匹配的地址 LEFT JOIN Address a ON pd.Data_Id = a.Data_Id ) SELECT CASE WHEN group_row_num = 1 THEN Data_Id ELSE NULL END AS Data_Id, CASE WHEN group_row_num = 1 THEN First_Name ELSE NULL END AS First_Name, CASE WHEN group_row_num = 1 THEN Last_Name ELSE NULL END AS Last_Name, Address_Type, address_data FROM join_result -- 强制排序保证同一Data_Id的地址行连续排列 ORDER BY Data_Id, group_row_num
效果与注意事项
- 最终输出完全匹配要求的展示样式:同个Data_Id下的第一条记录展示全部主表信息,后续关联地址行的主表字段为空
- 完全覆盖需求要求的三类场景:单地址用户(1条地址)、多地址用户(最多10条关联地址)、无地址用户(无关联地址)的输出都符合要求;其中无地址用户会单独占一行,主表字段正常展示,地址相关字段为空,不会被遗漏
- 地址的展示顺序可灵活调整:修改
ROW_NUMBER()里的ORDER BY条件,即可实现按地址类型、地址内容等规则排序 - 低版本数据库适配:如果使用的是不支持窗口函数的老旧数据库(如MySQL 5.x),可以用用户变量赋值的方式生成组内行号,整体逻辑和上述方案完全一致
内容的提问来源于stack exchange,提问作者Satyam Pisal
相关产品推荐
相关产品推荐

