使用 SQL SMS,如何将多行合并为一行,但保留所有列数据?

Using SQL SMS, how do I combine multiple rows into one row, but maintain all the column data?

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

 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 都有不同数量的药物和相应的填充日期。我想 return 那些没有数据要填写的列的空值。提前致谢。

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

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

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