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

将一对多关联的SQL查询结果展平为单行

实现SQL行转列:将同一预约的物品转为独立字段

你需要将Appt表与SuppliedGoods表关联后,把每个预约下的多个物品转为独立的列,每个预约仅显示一行,而非多行结果。以下是两种可行的解决方案:

方法1:条件聚合(通用SQL方言)

这是兼容性最好的方案,适用于几乎所有支持窗口函数的数据库(MySQL 8.0+、PostgreSQL、SQL Server、Oracle等)。

核心逻辑:

  1. 给每个预约下的物品生成唯一序号,区分第1、第2、第3个物品
  2. 通过CASE语句结合聚合函数MAX,将不同序号的物品映射到独立列
SELECT 
    a.ApptID,
    a.ApptDate,
    MAX(CASE WHEN sg.ItemSeq = 1 THEN sg.SuppliedGoodsName END) AS SuppliedGoodsName1,
    MAX(CASE WHEN sg.ItemSeq = 2 THEN sg.SuppliedGoodsName END) AS SuppliedGoodsName2,
    MAX(CASE WHEN sg.ItemSeq = 3 THEN sg.SuppliedGoodsName END) AS SuppliedGoodsName3
FROM Appt a
LEFT JOIN (
    -- 子查询:给每个ApptID下的物品按ID排序并生成序号
    SELECT 
        ApptID,
        SuppliedGoodsName,
        ROW_NUMBER() OVER (PARTITION BY ApptID ORDER BY ID) AS ItemSeq
    FROM SuppliedGoods
) sg ON a.ApptID = sg.ApptID
GROUP BY a.ApptID, a.ApptDate
ORDER BY a.ApptID;

结果说明:

  • 每个预约对应一行数据
  • 物品不足3个的位置会显示NULL(如ApptID=2的第3列)
  • 列名使用SuppliedGoodsName1/2/3避免重复(数据库不允许同名列)

方法2:使用PIVOT语法(部分数据库支持)

如果你的数据库支持PIVOT(如SQL Server、Oracle),可以用更简洁的语法实现:

SELECT 
    ApptID,
    ApptDate,
    [1] AS SuppliedGoodsName1,
    [2] AS SuppliedGoodsName2,
    [3] AS SuppliedGoodsName3
FROM (
    -- 源数据:关联两表并生成物品序号
    SELECT 
        a.ApptID,
        a.ApptDate,
        sg.SuppliedGoodsName,
        ROW_NUMBER() OVER (PARTITION BY a.ApptID ORDER BY sg.ID) AS ItemSeq
    FROM Appt a
    LEFT JOIN SuppliedGoods sg ON a.ApptID = sg.ApptID
) AS SourceTable
PIVOT (
    MAX(SuppliedGoodsName)
    FOR ItemSeq IN ([1], [2], [3])
) AS PivotTable
ORDER BY ApptID;

为什么之前的GROUP BY失败?

你之前直接GROUP BY时失败,是因为SuppliedGoodsName没有被包含在聚合函数中。每个预约分组下对应多个物品名称,数据库无法自动确定要保留哪个值。而上面的方案中,CASE+MAX本质是一种聚合逻辑:每个序号只对应一个物品名称,MAX会保留该值、忽略其他NULL,从而实现按序号拆分列。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 11:27:04