在 SQL 中将长表调整为宽表的形状

Reshape long to wide table in SQL

提问人:user12501522 提问时间:10/18/2023 最后编辑:Mr.Jonesuser12501522 更新时间:10/18/2023 访问量:47

问:

我有一个包含变量 ID、疫苗和日期的数据集。 有些疫苗只有一个日期,有些疫苗有一个 ID 有两个或三个日期。当我在 SQL 中创建表时,会为 具有两个或多个疫苗日期的 ID。请参阅以下示例:

编号 疫苗 日期
一个 流感 1/15/2005
一个 流感 3/25/2005
B 流感 1/15/2005
B 结核病 1/15/2005
B 结核病 2/15/2005
B 结核病 3/15/2005
B 流感 4/18/2005
C 流感 1/15/2005
C 结核病 5/21/2005

如何在SQL中创建如下表?

编号 疫苗 日期1 日期2 日期3
一个 流感 1/15/2005 3/25/2005
B 流感 1/15/2005 4/18/2005
B 结核病 1/15/2005 2/15/2005 3/15/2005
C 流感 1/15/2005
C 结核病 5/21/2005

谢谢

SQL 重塑 可折叠

评论

0赞 Mr.Jones 10/18/2023
到目前为止,您尝试过什么?您是否尝试过任何不起作用的 SQL 代码?
0赞 Ozan BAYRAM 10/18/2023
你为什么要创建它?您拥有数据,并用您的代码读取数据,并根据需要处理和显示数据。
0赞 jarlh 10/18/2023
您使用的是哪些 dbms?答案可能是使用特定于产品的功能。
0赞 jarlh 10/18/2023
当 A 接种第 4:4 剂时会发生什么?忽略、切换 1:st 日期或添加其他列?
0赞 user12501522 10/19/2023
感谢大家提供解决方案和意见。这两种解决方案都很好。

答:

1赞 Ozan BAYRAM 10/18/2023 #1

你可以尝试这样的东西:

SELECT 
    ID,
    Vaccine,
    MAX(CASE WHEN rn = 1 THEN Date END) AS Date1,
    MAX(CASE WHEN rn = 2 THEN Date END) AS Date2,
    MAX(CASE WHEN rn = 3 THEN Date END) AS Date3
FROM (
    SELECT 
        ID,
        Vaccine,
        Date,
        ROW_NUMBER() OVER (PARTITION BY ID, Vaccine ORDER BY Date) AS rn
    FROM 
        YourTableName
) AS subquery
GROUP BY 
    ID, Vaccine;

在此查询中:

  1. 内部子查询为 相同的 ID 和疫苗分区,按日期排序。
  2. 外部查询 使用 CASE 表达式根据日期的行号对日期进行透视 (rn)。MAX() 函数用于聚合每个 ID 的日期 和疫苗组合。

请确保将 YourTableName 替换为表的实际名称。此查询会将数据转换为所需的格式,其中 Date1、Date2 和 Date3 列指示每个 ID 和疫苗组合的不同日期。

1赞 BugHunter 10/18/2023 #2

若要将长 tb 重塑为宽 tb,可以使用条件聚合的组合。

SELECT
    ID,
    Vaccine,
    MAX(CASE WHEN rn = 1 THEN Date END) AS Date1,
    MAX(CASE WHEN rn = 2 THEN Date END) AS Date2,
    MAX(CASE WHEN rn = 3 THEN Date END) AS Date3
FROM (
    SELECT
        ID,
        Vaccine,
        Date,
        ROW_NUMBER() OVER (PARTITION BY ID, Vaccine ORDER BY Date) AS rn
    FROM TBName
) AS Ranked
GROUP BY ID, Vaccine, rn
HAVING MAX(CASE WHEN rn = 1 THEN Date END) IS NOT NULL;