将行转换为涉及日期的列

Posted

技术标签:

【中文标题】将行转换为涉及日期的列【英文标题】:Convert Rows to Columns involving Dates 【发布时间】:2021-11-03 06:18:31 【问题描述】:

我是一名具备 SQL 基础知识的 SAS 程序员。我正在尝试将 SAS 程序转换为 SQL 脚本,并且在 SQL Server 中将行转换为列时需要帮助。

我尝试了该论坛中提供的一些解决方案(如 PIVOT、多重连接等),但无法实现我所需要的。问题是,ID 的行数可能从 1 到 500(或更多)不等,我需要动态创建这些列。然而,在 SAS 中,我不必担心行数的变化,因为 SAS 会使用预定义的过程/方法(如 Proc Transpose 或数组)自动完成。

这是我正在尝试使用的一些示例数据。

感谢您在这方面的帮助。

ID  STARTDT ENDDT
1   1/1/2020    1/3/2020
1   2/25/2020   2/28/2020
1   3/10/2020   3/15/2020
2   1/1/2020    1/3/2020
2   2/25/2020   2/28/2020
2   3/10/2020   3/15/2020
2   3/20/2020   3/20/2020
2   3/25/2020   3/31/2020
3   1/1/2020    1/3/2020
4   2/25/2020   2/28/2020
4   3/10/2020   3/15/2020

所需的输出。

ID  STDT1   ENDT1   STDT2   ENDT2   STDT3   ENDT3   STDT4   ENDT4   STDT5   ENDT5 ........... STDT(MAX) ENDT(MAX)
1   1/1/2020    1/3/2020    2/25/2020   2/28/2020   3/10/2020   3/15/2020   
2   1/1/2020    1/3/2020    2/25/2020   2/28/2020   3/10/2020   3/15/2020   3/20/2020   3/20/2020   3/25/2020   3/31/2020
3   1/1/2020    1/3/2020        
4   2/25/2020   2/28/2020   3/10/2020   3/15/2020

【问题讨论】:

Dynamic pivot 请向我们展示您的尝试。 CREATE TABLE #TEMPDATES WITH (DISTRIBUTION = HASH(ID)) AS SELECT ID, STARTDT, ENDDATE, ROW_NUMBER() OVER(PARTITION BY ID ORDER BY STARTDT, ENDDATE) AS RNK 从 MYTABLE GO SELECT A .ID, A.STARTDT AS STDT1, A.ENDDATE AS ENDT1, B.STARTDT AS STDT2, B.ENDDATE AS ENDT2 FROM #TEMPDATES A INNER JOIN #TEMPDATES B ON A.ID = B.ID WHERE A.RNK = 1 AND B.RNK = 2; 请提供足够的代码,以便其他人更好地理解或重现问题。 【参考方案1】:

以下是您的问题的一种可能的解决方案:

-- create table
CREATE TABLE Dates
(
  ID INT,
  StartDt VARCHAR(20),
  EndDt VARCHAR(20)
)
-- Add sample data
INSERT INTO Dates VALUES (1, '1/1/2020', '1/3/2020')
INSERT INTO Dates VALUES (1, '2/25/2020', '2/28/2020')
INSERT INTO Dates VALUES (1, '3/10/2020', '3/15/2020')
INSERT INTO Dates VALUES (2, '1/1/2020' ,'1/3/2020')
INSERT INTO Dates VALUES (2, '2/25/2020', '2/28/2020')

-- Create a CTE to get the sequence for multiple occurrences of the same ID
-- Sequence1 is used for the second pivot on EndDt
WITH cte AS
(
SELECT
  [ID]
  ,[Sequence] = ROW_NUMBER() OVER(PARTITION BY [ID] ORDER BY [ID])
  ,[Sequence1] = 100 + ROW_NUMBER() OVER(PARTITION BY [ID] ORDER BY [ID])
  ,[StartDt]
  ,[EndDt]
FROM Dates
)
-- SELECY with PIVOT on multiple columns
SELECT
  [ID]
  ,[1] AS startdt1
  ,[101] AS enddt1
  ,[2] AS startdt2
  ,[102] AS enddt2
  ,[3] AS startdt3
  ,[103] AS enddt3
FROM cte x
PIVOT
(
  MAX(StartDt)
  FOR [Sequence] IN ([1], [2], [3])
) p1

PIVOT
(
  MAX(EndDt)
  FOR [Sequence1] IN ([101], [102], [103])
) p2
ORDER BY ID

参考: https://docs.microsoft.com/en-us/sql/t-sql/queries/from-using-pivot-and-unpivot?view=sql-server-ver15

【讨论】:

您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。

以上是关于将行转换为涉及日期的列的主要内容,如果未能解决你的问题,请参考以下文章

需要将行转换为oracle中相似ID的列

将行值转换为火花数据框中的列数组

如何将行转换为按行数创建标题的列

如何使用枢轴将行转换为postgres中的列?让我来计算一下

Postgres - 将行转换为两个表中的列

如何根据日期列将行转换为列?