【问题标题】:SQL Combine multiple rows from one table into one row with multiple columnsSQL 将一张表中的多行合并为一行多列
【发布时间】:2016-03-07 06:19:06
【问题描述】:

如果我有日期和时间相同或不同的数据,如下所示:

ID    Date               LOC
1     2015-12-02 10:05   A
1     2015-12-02 10:05   B2
2     2015-12-02 10:05   D
2     2015-12-02 10:05   A7P 
2     2015-12-02 10:06   AD

有没有办法显示以下内容:

ID   DATE1             LOC1  DATE 2            LOC2  DATE 3            LOC3
1    2015-12-02 10:05  A     2015-12-02 10:05  B2
2    2015-12-02 10:05  D     2015-12-02 10:05  A7P   
2    2015-12-02 10:06  AD

所以会有多行 ID 相同但日期和时间不同的行?

我使用了下面的分区示例,这非常适合我最初要求的将数据放入一行。但是当ID相同但日期和时间不同时,是否可以显示多行。

以下是已回答的原始问题..

我查看了与此问题相关的所有答案,但找不到任何有效的代码,而且很多问题都与两个表有关。

我有一个表,其中包含多行数据和包含不同数据类型的多列,例如

ID    Date               LOC
1     2015-11-05 10:05   A
1     2015-12-02 10:06   B2
2     2015-12-02 10:05   D
2     2015-12-02 10:05   A7P 
2     2015-12-02 10:06   AD

我只要求每个 ID 有一行,所有数据位于多列中,例如

ID   DATE1             LOC1  DATE 2            LOC2  DATE 3            LOC3
1    2015-11-05 10:05  A     2015-12-02 10:06  B2
2    2015-12-02 10:05  D     2015-12-02 10:05  A7P   2015-12-02 10:06  AD

这些可以有重复的数据和同一 ID 的一行或多行。

我已经尝试了一些数据透视/取消数据透视 sql 代码,但我得到一个关于 unpivot 中不同类型的错误。

任何帮助将不胜感激。

【问题讨论】:

  • 你最多有 3 对柱子吗?
  • 嗨。它会有所不同,最多可能有 6 个。
  • 如果您希望 id 和 datetime 匹配,那么只需将其包含在连接中即可。连接是使事情保持在同一行的原因。
  • 谢谢霍根。我试过了,它们仍然显示在不同的行上。但是当我将日期添加到“PARTITION BY ID,日期”时,它起作用了
  • 是的,这是有道理的,但请确保将日期添加到联接中,否则您可能会遇到错误——我更改了答案中的代码。

标签: sql sql-server-2008


【解决方案1】:

这是基本的方法,先做row_number然后做一个join

WITH TAB_RN AS
(
  SELECT ID, Date, LOC, ROW_NUMBER() OVER (PARTITION BY ID, Date ORDER BY LOC) AS RN
  FROM YOUR_TABLE
)
SELECT T1.ID, 
       T1.Date AS DATE1, T1.LOC AS LOC1,
       T2.Date AS DATE2, T2.LOC AS LOC2,
       T3.Date AS DATE3, T3.LOC AS LOC3
FROM TAB_RN T1
LEFT JOIN TAB_RN T2 ON T1.ID = T2.ID AND T1.Date = T2.Date AND T2.RN = 2
LEFT JOIN TAB_RN T3 ON T1.ID = T3.ID AND T1.Date = T2.Date AND T3.RN = 3
WHERE T1.RN = 1

如果你不知道会有“多少”那么你必须使用它作为模板来制作动态sql。

【讨论】:

  • 谢谢。我会试试的。
  • 通常人们实际上想要一个逗号分隔的列表。 FOR XML 有一个技巧,不需要知道有多少列表项。
  • 感谢您的帮助 - 它的工作原理正是我想要的。
  • @Mally - 如果它对您有帮助,您应该投票给答案,并在给其他人时间回答后将其选为“正确答案”。这是对本网站的期望。
  • 好的,我会的。再次感谢。
【解决方案2】:

我想我已经设法得到了这个,但我不确定这个是否有错误。

我创建了一个示例表用于测试目的

CREATE TABLE Trace (
    TraceID INT IDENTITY(1,1)
    , ID INT
    , [Date] DATETIME
    , LOC NVARCHAR(50)
)

INSERT INTO Trace (ID, [Date], LOC)
VALUES
(1,'2015-12-02 10:05','A'),
(1,'2015-12-02 10:05','B2'),
(2,'2015-12-02 10:05','D'),
(2,'2015-12-02 10:05','A7P'),
(2,'2015-12-02 10:06','AD')

如果您希望根据每个 ID 的最大位置数(灵活列)获取记录,您可以尝试下面的脚本。

   -- build up table to keep the values in 1 column and make a flag (StatusCode) out of it
        SELECT 
            ROW_NUMBER() OVER (PARTITION BY ID, StatusCode ORDER BY TraceID, Pos) AS idx
            , *
        INTO #resultBuildUp 
        FROM (
                SELECT
                    TraceID
                    , 2 AS [Pos]
                    , [ID]
                    , 'LOC' + CONVERT(NVARCHAR(50),(ROW_NUMBER() OVER (PARTITION BY ID, [Date] ORDER BY TraceID))) AS StatusCode
                    , LOC AS [val]
                FROM Trace
            UNION ALL
                SELECT
                    TraceID
                    , 1 AS [Pos]
                    , [ID]
                    , 'DATE ' + CONVERT(NVARCHAR(50),(ROW_NUMBER() OVER (PARTITION BY ID, [Date] ORDER BY TraceID))) AS StatusCode
                    , REPLACE(CONVERT(NVARCHAR(50),[Date],111),'/','-') + ' ' + CONVERT(NVARCHAR(50),[Date],108) AS [val]
                FROM Trace
        ) AS T

    --this is a builder to create the "select" columns for PIVOT

        SELECT
            StatusCode
        INTO #tmpDistinctColumns
        FROM #resultBuildUp
        GROUP BY
            StatusCode
        ORDER BY 
            min(TraceID)
            , min(Pos)

        DECLARE @distinct NVARCHAR(MAX) = ''

        SET @distinct = (SELECT '[' + StatusCode + '],' AS [text()] FROM #tmpDistinctColumns FOR XML PATH(''))
        SET @distinct = SUBSTRING(@distinct, 0, LEN(@distinct))

-- and lastly, the pivot query wherein I hid the position modifier(idx) for the query

EXEC ('
SELECT
    ID
    , ' + @distinct + '
FROM (
    SELECT
        idx,
        ID,
        StatusCode,
        val
    FROM #resultBuildUp
) AS s 
PIVOT
(
    MAX(Val)
    FOR StatusCode IN (' + @distinct + ')
) AS pvt
')

-- drop all temporary tables built from above script
drop table #resultBuildUp
drop table #tmpDistinctColumns

您的要求中指定的“时间”也已考虑,结果应如下所示

【讨论】:

    猜你喜欢
    • 2014-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-09
    • 1970-01-01
    • 2012-05-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多