SQL 将多行转置到不同的列

Posted

技术标签:

【中文标题】SQL 将多行转置到不同的列【英文标题】:SQL transpose multiple rows to different columns 【发布时间】:2021-10-15 11:43:03 【问题描述】:

我有 SQL server 数据表,像这样:

ID SYMPTOM1 SYMPTOM2
1 A B
1 C D
2 E F
3 A C
3 D E

我想得到这个:

ID SYMPTOM1 SYMPTOM2 SYMPTOM3 SYMPTOM4
1 A B C D
2 E F
3 A C D E

这应该是一个“简单”的支点,但我想不通。 如何编写 SQL 查询?

*编辑

对不起,我忽略了一个重要的细节。表中的行数非常大,大约 500.000,因此 ID 非常大。

【问题讨论】:

您希望它作为一个使用 tsql-PIVOT 的枢轴还是一个条件聚合? (即 sqlserver 特定解决方案或 SQL 通用解决方案)。症状表达的顺序重要吗? 这能回答你的问题吗? Group by column and multiple Rows into One Row multiple columns 【参考方案1】:

您可以将其作为自连接进行 - 使用行号来获得另一列 1 或 2(取决于 ID 出现的次数),1 应该始终出现,2 有时出现,所以左加入这些行2 到那些有 1 的行(基于 id)给你最终结果..

WITH x AS(
  SELECT
    t.ID,
    t.SYMPTOM1,
    t.SYMPTOM2,
    ROW_NUMBER() OVER (PARTITION BY t.ID ORDER BY t.SYMPTOM1) as rn
  FROM t
)

SELECT
  *
FROM
  x x1
  LEFT JOIN x x2 ON x1.id = x2.id AND x1.rn = 1 AND x2.rn = 2

【讨论】:

听起来效率低下 衡量,不要猜测 @spiderman 错字,谢谢指出【参考方案2】:

您可以以行号为轴

SELECT
  t.ID,
  SYMPTOM1 = MAX(CASE WHEN t.rn = 1 THEN t.SYMPTOM1 END),
  SYMPTOM2 = MAX(CASE WHEN t.rn = 1 THEN t.SYMPTOM2 END),
  SYMPTOM3 = MAX(CASE WHEN t.rn = 2 THEN t.SYMPTOM1 END),
  SYMPTOM4 = MAX(CASE WHEN t.rn = 2 THEN t.SYMPTOM2 END)
FROM (
    SELECT
      t.*,
      rn = ROW_NUMBER() OVER (PARTITION BY t.ID ORDER BY (SELECT 1))
    FROM YourTable t
) t
GROUP BY t.ID;

【讨论】:

这里实际上不需要反透视。只需对RN 的每个值进行 2 个条件聚合; 1 个用于Symptom1,另一个用于Symptom2 非常正确,谢谢

以上是关于SQL 将多行转置到不同的列的主要内容,如果未能解决你的问题,请参考以下文章

使用 serde Rust 将数据从记录转置到没有中间结构的列

SQL Server 转置(可能是转置?)多行到一列

将 SQL 行标题转置到第一列

转置并插入具有不同值的多行

如何将多行转换为不同的列?

Oracle:多列转多行