【问题标题】:Using SQL SMS, how do I combine multiple rows into one row, but maintain all the column data?使用 SQL SMS,如何将多行合并为一行,但保留所有列数据?
【发布时间】:2015-11-27 09:23:32
【问题描述】:

我正在处理的数据目前采用以下形式:

 ID     Sex     Treatment    FillDate     
 1      M       ziprosidone  10/01/98     
 1      M       ziprosidone  10/15/98
 1      M       ziprosidone  10/29/98
 1      M       ambien       01/07/99
 1      M       ambien       01/14/99
 2      F       telaprevir   03/08/92
 2      F       telaprevir   03/20/92
 2      F       telaprevir   04/01/92

我想编写 SQL 代码来获取以下形式的数据:

 ID     Sex     DrugFill1     FillDate1_1     FillDate1_2     FillDate1_3    DrugFill2     FillDate2_1     FillDate2_2     FillDate2_3     
 1      M       ziprosidone   10/01/98        10/15/98        10/29/98       ambien        01/07/99        01/14/99        null
 2      F       telaprevir    03/08/92        03/20/92        04/01/92       null          null            null            null

另外我想指出,我有超过 10,000 个 ID,每个 ID 都有不同数量的药物和相应的填充日期。我想为那些没有数据要填写的列返回空值。提前致谢。

【问题讨论】:

  • 如果在 RDBMS 中执行此操作,则这称为枢轴。但更好的做法是处理应用程序级代码中的数据显示问题,例如一个简单的 PHP 循环(如果可用)。
  • @Justin,你检查我的答案了吗?如果有帮助,请投票和/或标记为已接受...谢谢
  • @Shnugo 抱歉耽搁了,我正在旅行。感谢您的详细回复,您的代码和逻辑似乎与我正在寻找的非常接近。我很感激。
  • @Shnugo 问题,在第一个SELECT DISTINCT ID, Sex FROM @tbl 中是否有必要在其中包含 Sex 变量?我只是问,因为假设除了 Sex 之外我还有一个 Race 列,我是否也需要将它包含在第一个 SELECT DISTINCT 语句中?谢谢!
  • @Justin,嗨,是的,第一条语句包含不随治疗而改变的数据。顺便说一句:最好在它所属的答案下方设置这样的评论......

标签: mysql sql-server merge rows


【解决方案1】:

此解决方案非常接近您的需求。如果您需要进一步帮助以“并排”将药物排成一排,请告诉我。实际上我不会这样做...将其粘贴到一个空的查询窗口中并执行。适应您的需求...

编辑:将其更改为您的新药物名称。

DECLARE @tbl TABLE(ID INT,Sex VARCHAR(1),Treatment VARCHAR(30),FillDate DATETIME);

INSERT INTO @tbl VALUES
 (1,'M','ziprosidone',{ts'1998-01-01 00:00:00'})     
,(1,'M','ziprosidone',{ts'1998-10-15 00:00:00'})
,(1,'M','ziprosidone',{ts'1998-10-29 00:00:00'})
,(1,'M','ambien',{ts'1999-01-07 00:00:00'})
,(1,'M','ambien',{ts'1999-01-14 00:00:00'})
,(2,'F','telaprevir',{ts'1992-03-08 00:00:00'})
,(2,'F','telaprevir',{ts'1992-03-02 00:00:00'})
,(2,'F','telaprevir',{ts'1992-04-01 00:00:00'});

WITH DistinctIDs AS
(
    SELECT DISTINCT ID,Sex FROM @tbl
)
,DistinctDrugs AS
(
    SELECT DISTINCT DistinctIDs.ID
                   ,DistinctIDs.Sex
                   ,tbl.Treatment
                   ,'Drug_' + CAST(ROW_NUMBER() OVER(PARTITION BY tbl.ID,tbl.Treatment ORDER BY tbl.Treatment) AS VARCHAR(100)) AS PivotColumnName 
    FROM DistinctIDs
        INNER JOIN @tbl AS tbl ON DistinctIDs.ID=tbl.ID
)
SELECT p.ID 
      ,p.Sex
      ,p.Treatment
      ,CAST(p.Drug_1 AS XML).value('/root[1]/item[1]/FillDate[1]','datetime') AS Date_1
      ,CAST(p.Drug_1 AS XML).value('/root[1]/item[2]/FillDate[1]','datetime') AS Date_2
      ,CAST(p.Drug_1 AS XML).value('/root[1]/item[3]/FillDate[1]','datetime') AS Date_3
FROM
(
    SELECT DistinctDrugs.*
          ,SubRows.XMLContent
    FROM DistinctDrugs
    CROSS APPLY
    (
        SELECT tbl.FillDate
        FROM @tbl  AS tbl
        WHERE tbl.ID=DistinctDrugs.ID AND tbl.Treatment=DistinctDrugs.Treatment
        FOR XML PATH('item'),ROOT('root')
    ) AS SubRows(XMLContent)
) AS DataToPivot
PIVOT
(
    MIN(XMLContent) FOR PivotColumnName IN(Drug_1,Drug_2,Drug_3 /*as many as needed*/)
) AS p

【讨论】:

  • 您好,感谢您的评论提示。我运行了代码,它似乎为 ID=1 创建了两行。换句话说,有一行 ID=1 和 Drug1 及其填充日期,然后第二行 ID=1 和 Drug2 及其填充日期。我希望每个 ID 有一个唯一的行,其中包含所有相应的药物和填写该行中该 ID 的日期..感谢您迄今为止的所有帮助!
  • @Justin,这正是我在答案标题中写的 ;-) 我明天会帮你,现在很晚 ;-)
  • 哎呀,我刚刚注意到你写的正是那个! :P 太棒了,我真的很感激。晚安。
  • @Justin,如果您对此表示赞赏,最好取消已接受的支票;-)
  • 完成 :) 抱歉,我不知道那方面的协议。此外,您会注意到我将我的帖子从 Drug1、Drug2 等编辑为实际的药物名称,正如我在运行代码时意识到的那样,这很重要,而且我的数据不是“drug1”而是实际的药名。干杯
猜你喜欢
  • 2012-11-04
  • 2018-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-28
  • 2015-09-17
  • 2018-04-22
相关资源
最近更新 更多