在TSQL中按案例编号组合多行

时间:2017-09-18 22:05:01

标签: sql sql-server tsql pivot

我是SQL的新手(更确切地说是T-SQL),我似乎无法绕过这个。我确定有一个简单的解决方案,我只是没想到(可能涉及子查询和/或表格枢轴)。但我希望你们中的一个SQL高手可以帮助一个无能的新手。

基本上,我需要转换这些数据:

CaseNumber|DecisionNumber|Date       |Decision
----------+--------------+-----------+--------
444       |29833         |04/05/2005 |Sell
444       |29777         |05/10/2006 |Sell
444       |29654         |08/19/2007 |Buy
468       |29230         |08/19/2006 |Sell
468       |29192         |08/19/2011 |Sell

进入这个结果:

CaseNumber|DecisionNumber1|Date1       |Decision1|DecisionNumber2|Date2       |Decision2|DecisionNumber3|Date3       |Decision3
----------+---------------+------------+---------+---------------+------------+---------+---------------+------------+---------
444       |29833          |04/05/2005  |Sell     |29777          |05/10/2006  |Sell     |29654          |08/19/2007  |Buy
468       |29230          |08/19/2006  |Sell     |29192          |08/19/2011  |Sell     |NULL           |NULL        |NULL

任何想法都会受到青睐。

1 个答案:

答案 0 :(得分:1)

您尝试执行的操作的问题在于您尝试一次调整多个列。这可以使用unpivot然后pivot来完成。像这样:

WITH CTE
AS
(
  SELECT 
     CAST(CaseNumber AS NVARCHAR(50)) AS CaseNumber
     ,CAST(DecisionNumber AS NVARCHAR(50)) AS DecisionNumber
     ,CAST(Date AS NVARCHAR(50)) AS [Date]
    ,ROW_NUMBER() OVER(PARTITION BY [CaseNumber] ORDER BY DecisionNumber DESC) AS RN
  FROM Table1
), unpivoted
AS
(
  SELECT CaseNumber, val, col + ' ' + CAST(RN AS NVARCHAR(50)) AS col
  FROM CTE 
  UNPIVOT
  (
    val
    FOR col IN(DecisionNumber, Date)
  ) AS u
)
SELECT *
FROM unpivoted AS u
PIVOT
(
  MAX(val)
  FOR col IN([DecisionNumber 1], [Date 1], 
             [DecisionNumber 2], [Date 2],
             [DecisionNumber 3], [Date 3])
) AS p;

这会给你:

| CaseNumber | DecisionNumber 1 |     Date 1 | DecisionNumber 2 |     Date 2 | DecisionNumber 3 |     Date 3 |
|------------|------------------|------------|------------------|------------|------------------|------------|
|        444 |            29833 | 2005-04-05 |            29777 | 2006-05-10 |            29654 | 2007-08-19 |
|        468 |            29230 | 2006-08-19 |            29192 | 2011-08-19 |           (null) |     (null) |

但是,如果您要对任意数量的decisionnumberdate执行此操作,则可以执行以下操作:

DECLARE @cols AS NVARCHAR(MAX);
DECLARE @query AS NVARCHAR(MAX);

WITH CTE
AS
(
  SELECT 
     CAST(CaseNumber AS NVARCHAR(50)) AS CaseNumber
     ,CAST(DecisionNumber AS NVARCHAR(50)) AS DecisionNumber
     ,CAST(Date AS NVARCHAR(50)) AS [Date]
    ,ROW_NUMBER() OVER(PARTITION BY [CaseNumber] ORDER BY DecisionNumber DESC) AS RN
  FROM Table1
), Data
AS
(
  SELECT col, MAX(RN) AS RN
  FROM
  (
    SELECT RN, col + CAST(RN AS NVARCHAR(50)) AS col
    FROM CTE 
    UNPIVOT
    (
      val
      FOR col IN(DecisionNumber, Date)
    ) AS u
  ) AS t
  GROUP BY col
)
select @cols = STUFF((SELECT ',' +
                        QUOTENAME(col)
                      FROM Data
                      ORDER BY RN
                      FOR XML PATH(''), TYPE
                     ).value('.', 'NVARCHAR(MAX)') 
                        , 1, 1, '');

SELECT @query = 'WITH CTE
AS
(
  SELECT 
     CAST(CaseNumber AS NVARCHAR(50)) AS CaseNumber
     ,CAST(DecisionNumber AS NVARCHAR(50)) AS DecisionNumber
     ,CAST(Date AS NVARCHAR(50)) AS [Date]
    ,ROW_NUMBER() OVER(PARTITION BY [CaseNumber] ORDER BY DecisionNumber DESC) AS RN
  FROM Table1
), unpivoted
AS
(
  SELECT CaseNumber, val, col + CAST(RN AS NVARCHAR(50)) AS col
  FROM CTE 
  UNPIVOT
  (
    val
    FOR col IN(DecisionNumber, Date)
  ) AS u
)
SELECT *
FROM unpivoted AS u
PIVOT
(
  MAX(val)
  FOR col IN('+ @cols + ')
) AS p;';


EXECUTE(@query);