MSSQL使用双列将2行合并为1

时间:2017-12-15 07:27:51

标签: sql sql-server

我可能没有正确搜索但是找不到这个。我想将2行中的数据合并为1行,其中包含两列。首先选择具有最新时间戳的那个。然后,如果有超过2行结果,则只取前2行。下面的示例数据和所需结果

来源:

ID  Height  Color   Type    TimeStamp
1   6       Green   Plant   2017-09-23
1   24      Red     Tree    2017-09-15
1   33      Pink    Shrub   2016-05-14
2   12      Blue    Car     2017-03-21
2   88      Pink    Truck   2017-11-22

期望的结果:

ID  Height1 Color1  Type1   Height2 Color2  Type2
1   6       Green   Plant   24      Red     Tree
2   88      Pink    Truck   12      Blue    Car

现在已经磕磕绊绊了几天。帮助!

3 个答案:

答案 0 :(得分:2)

使用OUTER APPLY的方式:

SELECT TOP 1 WITH TIES  y.ID,
                        y.Height as Height1,
                        y.Color as Color1,
                        y.[Type] as [Type1],
                        t.Height2,
                        t.Color2,
                        t.[Type2]
FROM YourTabel y
OUTER APPLY (
    SELECT TOP 1    Height as Height2,
                    Color as Color2,
                    [Type] as [Type2]
    FROM YourTabel 
    WHERE ID = y.ID AND [TimeStamp] < y.[TimeStamp]
    ORDER BY [TimeStamp] DESC
) as t
ORDER BY ROW_NUMBER() OVER (PARTITION BY y.ID ORDER BY y.[TimeStamp] DESC)

输出:

ID  Height1 Color1  Type1   Height2 Color2  Type2
1   6       Green   Plant   24      Red     Tree
2   88      Pink    Truck   12      Blue    Car

对于 SQL Server 2012 及更高版本,您可以使用LAG

SELECT TOP 1 WITH TIES  y.ID,
                        y.Height as Height1,
                        y.Color as Color1,
                        y.[Type] as [Type1],
                        LAG(y.Height) OVER (PARTITION BY y.ID ORDER BY y.[TimeStamp] ASC) Height2,
                        LAG(y.Color) OVER (PARTITION BY y.ID ORDER BY y.[TimeStamp] ASC) Color2,
                        LAG(y.[Type]) OVER (PARTITION BY y.ID ORDER BY y.[TimeStamp] ASC) [Type2]
FROM YourTabel y
ORDER BY ROW_NUMBER() OVER (PARTITION BY y.ID ORDER BY y.[TimeStamp] DESC)

答案 1 :(得分:0)

试试这个(假设您的表名是t1)

;WITH CTE
AS
(
   SELECT
  RN = ROW_NUMBER() OVER(partition by id ORDER BY TimeStamp desc,ID),    
  *
  FROM T1
)
SELECT
ID = ROW_NUMBER() OVER(ORDER BY C1.ID), 
C1.HEIGHT AS "HEIGHT1",
C1.COLOR Color1,  
C1.TYPE  Type1,   
C2.HEIGHT Height2, 
C2.COLOR Color2,  
C2.TYPE Type2
FROM CTE C1
  LEFT JOIN CTE C2
    ON C1.RN%2 = 1
      AND C2.RN%2 = 0
    WHERE C1.RN = C2.RN-1
      and c1.rn <3
      and c1.id = c2.id

检查DEMO此处

答案 2 :(得分:0)

玩这个:

DECLARE @DataSource TABLE
(
    [ID] INT
   ,[Height] INT
   ,[Color] VARCHAR(12)
   ,[Type] VARCHAR(12)
   ,[TimeStamp] DATETIME2
);

INSERT INTO @DataSource ([ID], [Height], [Color], [Type], [TimeStamp])
VALUES ('1', '6', 'Green', 'Plant', '2017-09-23')
      ,('1', '24', 'Red', 'Tree', ' 2017-09-15')
      ,('1', '33', 'Pink', 'Shrub', '2016-05-14')
      ,('1', '33', 'Pink', 'Shrub 1', '2016-05-13')
      ,('1', '33', 'Pink', 'Shrub 2', '2016-05-12')
      ,('1', '33', 'Pink', 'Shrub 3', '2016-05-11')
      ,('2', '12', 'Blue', 'Car', '  2017-03-21')
      ,('2', '88', 'Pink', 'Truck', '2017-11-22')
      ,('3', '12', 'test', 'test 2', '2017-11-22');

SELECT [ID]
      ,MAX(CASE WHEN [RowID] = 1 THEN [Height] ELSE NULL END) AS [Height1]
      ,MAX(CASE WHEN [RowID] = 1 THEN [Color] ELSE NULL END) AS [Color1]
      ,MAX(CASE WHEN [RowID] = 1 THEN [Type] ELSE NULL END) AS [Type1]
      ,MAX(CASE WHEN [RowID] = 2 THEN [Height] ELSE NULL END) AS [Height2]
      ,MAX(CASE WHEN [RowID] = 2 THEN [Color] ELSE NULL END) AS [Color2]
      ,MAX(CASE WHEN [RowID] = 2 THEN [Type] ELSE NULL END) AS [Type2]
FROM
(
    SELECT TOP (4) WITH TIES *
          ,ROW_NUMBER() OVER (PARTITION BY [ID] ORDER BY [TimeStamp] DESC) AS [RowID]
    FROM @DataSource
    ORDER BY [RowID]
) DS
GROUP BY [ID];

enter image description here

相关问题