如何将SQL JOIN结果合并为单行?多ItemType预订数据处理
解决Booking记录按ItemType合并为单行的问题
要实现将同一BookingId下ItemType为1000和2000的记录合并为单行的需求,核心是行转列操作,你的原查询因自连接导致生成多行,以下是两种可行的解决方案:
方案一:GROUP BY + MAX(CASE) 通用写法
适用于绝大多数SQL数据库,逻辑清晰且兼容性强:
SELECT B.BookingID, B.BookingDate, B.Name, MAX(CASE WHEN IM.ItemType = 1000 THEN IM.ItemName END) AS [ItemName(1000)], MAX(CASE WHEN IM.ItemType = 2000 THEN IM.ItemName END) AS [ItemName(2000)] FROM BOOKINGS B JOIN ItemMapping IM ON B.ItemCode = IM.Code WHERE IM.ItemType IN (1000, 2000) GROUP BY B.BookingID, B.BookingDate, B.Name -- 可选:仅保留同时包含1000和2000类型的预订,取消注释下方行 -- HAVING COUNT(DISTINCT IM.ItemType) = 2
逻辑说明:
- 通过
CASE语句分别提取对应ItemType的ItemName,非目标类型的结果为NULL - 用
MAX()聚合函数忽略NULL,将同一BookingId下的多行数据合并为单行 GROUP BY按预订唯一标识分组,确保每个BookingId仅返回一行
方案二:PIVOT 简洁写法(限支持PIVOT的数据库如SQL Server)
如果你的数据库支持PIVOT语法,可以用更简洁的方式实现:
SELECT BookingID, BookingDate, Name, [1000] AS [ItemName(1000)], [2000] AS [ItemName(2000)] FROM ( SELECT B.BookingID, B.BookingDate, B.Name, IM.ItemType, IM.ItemName FROM BOOKINGS B JOIN ItemMapping IM ON B.ItemCode = IM.Code WHERE IM.ItemType IN (1000, 2000) ) AS SourceTable PIVOT ( MAX(ItemName) FOR ItemType IN ([1000], [2000]) ) AS PivotTable
逻辑说明:
- 子查询先筛选出目标ItemType的基础数据
- 利用PIVOT将
ItemType的行值直接转换为列,通过MAX()聚合获取对应ItemName
原查询问题总结
- 自连接
Bookings表导致同一BookingId生成多条互补记录(一行仅1000列有值,一行仅2000列有值),DISTINCT无法合并这类行 ISNULL(I.ItemName, I.ItemName)属于冗余写法,直接使用I.ItemName即可- WHERE条件的强匹配会过滤掉仅存在单一目标ItemType的预订,且自连接会产生不必要的笛卡尔积
内容的提问来源于stack exchange,提问作者Jenifer
相关产品推荐
相关产品推荐

