MySQL INNER JOIN关联表后将多行地址数据合并为单行的实现方案
你遇到的问题本质是行转列的常见场景:关联后GPS表的两个不同类型的地址分散在两行,你需要把它们合并到同一行的两个不同字段里。
你最初的CASE判断是行级逻辑,每行只能匹配到一种AddType,所以另一个字段必然为NULL。加了GROUP BY之后没有对CASE输出的结果做聚合,数据库默认只会取分组内第一条记录的值,自然会出现另一个字段为NULL的情况。
方案1:分组+聚合函数(推荐,逻辑简单兼容性好)
用MAX/MIN聚合函数忽略NULL值,提取对应类型的地址:
SELECT ls.LoadNumber, ls.LoadDate, MAX(CASE WHEN gps.AddType = 'C' THEN gps.AddressCode END) AS SourceCode, MAX(CASE WHEN gps.AddType = 'D' THEN gps.AddressCode END) AS DestinationCode FROM LoadSchedule AS ls INNER JOIN GpsTable AS gps ON gps.LoadNumber = ls.LoadNumber WHERE ls.LoadDate >= '2021-08-10' GROUP BY ls.LoadNumber, ls.LoadDate
注意:GROUP BY需要带上所有非聚合的查询字段(这里是LoadNumber和LoadDate),符合SQL标准语法,避免部分数据库开启严格模式时报错。
方案2:多次关联GPS表
分别关联C和D类型的GPS记录,不用分组也能实现效果:
SELECT ls.LoadNumber, ls.LoadDate, gps_c.AddressCode AS SourceCode, gps_d.AddressCode AS DestinationCode FROM LoadSchedule AS ls LEFT JOIN GpsTable AS gps_c ON gps_c.LoadNumber = ls.LoadNumber AND gps_c.AddType = 'C' LEFT JOIN GpsTable AS gps_d ON gps_d.LoadNumber = ls.LoadNumber AND gps_d.AddType = 'D' WHERE ls.LoadDate >= '2021-08-10'
如果你的业务中存在同一个LoadNumber有多个同类型地址的情况,可以根据需求调整:比如拼接多个地址用GROUP_CONCAT(MySQL)/STRING_AGG(PostgreSQL、SQL Server),或者加条件取优先级最高的一条地址即可。
内容的提问来源于stack exchange,提问作者hugovl
相关产品推荐
相关产品推荐

