SQL查询 - 几乎像数据透视表一样吗?

时间:2012-03-29 20:48:23

标签: sql-server pivot

关于SQL场景的另一个愚蠢的问题。

给出如下数据:

FieldKey    DocumentKey FieldId FieldValue
1   00001c55-aab3-4df8-a07e-8eac162fa075    TITLE   Mass Import 18355
2   00001c55-aab3-4df8-a07e-8eac162fa075    1   00001c55-aab3-4df8-a07e-8eac162fa075
3   00001c55-aab3-4df8-a07e-8eac162fa075    2   9F-2F-CF-76-27-E7-5B-C9-27-CE-23-45-68-3F-E2-89
4   00001c55-aab3-4df8-a07e-8eac162fa075    3   18355
5   00001c55-aab3-4df8-a07e-8eac162fa075    4   94-3C-84-B1-6A-AA-FD-25-F1-C0-D2-43-CD-D3-57-D6
6   00001c55-aab3-4df8-a07e-8eac162fa075    5   Created by C# mass import
7   00002205-00D3-4495-B65A-A7B1FD2AE7F2    TITLE   Mass Import 1494780
8   00002205-00D3-4495-B65A-A7B1FD2AE7F2    1   00002205-00D3-4495-B65A-A7B1FD2AE7F2
9   00002205-00D3-4495-B65A-A7B1FD2AE7F2    2   870386312
10  00002205-00D3-4495-B65A-A7B1FD2AE7F2    3   1494780
11  00002205-00D3-4495-B65A-A7B1FD2AE7F2    4   -1929051324
13  00002342-6de0-4110-b576-fd32f96b2858    TITLE   Mass Import 387008
14  00002342-6de0-4110-b576-fd32f96b2858    1   00002342-6de0-4110-b576-fd32f96b2858
15  00002342-6de0-4110-b576-fd32f96b2858    2   B0-CB-DF-ED-48-DC-C4-E8-B0-6F-1B-1D-81-2D-6D-51
16  00002342-6de0-4110-b576-fd32f96b2858    3   387008

使用表格结构:

[FieldKey] [bigint] IDENTITY(1,1) NOT NULL,
[DocumentKey] [char](36) NOT NULL,
[FieldId] [varchar](10) NOT NULL,
[FieldValue] [varchar](255) NOT NULL

水平翻转此数据的最佳方法是什么?理想的情况是:

DocumentKey                             TITLE    1    2    3    4    5
00001c55-aab3-4df8-a07e-8eac162fa075    mytitle  val1 val2 val3 val4 val5
00002205-00D3-4495-B65A-A7B1FD2AE7F2    mytitle2 val6 val7 val8 val9
00002342-6de0-4110-b576-fd32f96b2858    mytitle3 vl10 vl11 vl12

我认为数据透视表可能有效并且很接近,但问题是我不需要SQL数据透视表所需的聚合。我只是想翻转数据。列数(在我的示例中为1-5加上TITLE)可以是TITLE加1-30之间的任何位置。

也许我只是在密集,但任何想法都会受到赞赏。

2 个答案:

答案 0 :(得分:2)

如果您使用的是SQL Server 2005+,则可以使用PIVOT运算符。

select [DocumentKey], [TITLE], [1], [2], [3], [4], [5] 
from (select [DocumentKey], FieldId, FieldValue from TableName) t
    pivot (max(FieldValue) for FieldID in ([TITLE], [1], [2], [3], [4], [5])) as pvt
order by [DocumentKey]

您必须添加其他列,6 - 30。

答案 1 :(得分:2)

我认为您使用PIVOT走在正确的轨道上。您将在值列上有一个聚合。但正如你所说,你将有1-30列加上标题栏。这需要动态支点

这是一个建议(仅适用于SQL Server 2005 +):

测试数据

CREATE TABLE Table1
(
    [FieldKey] [bigint] NOT NULL,
    [DocumentKey] [char](36) NOT NULL,
    [FieldId] [varchar](10) NOT NULL,
    [FieldValue] [varchar](255) NOT NULL
)
INSERT INTO Table1
VALUES
    (1,'00001c55-aab3-4df8-a07e-8eac162fa075','TITLE','Mass Import 18355'),
    (2,'00001c55-aab3-4df8-a07e-8eac162fa075','1','00001c55-aab3-4df8-a07e-8eac162fa075'),
    (3,'00001c55-aab3-4df8-a07e-8eac162fa075','2','9F-2F-CF-76-27-E7-5B-C9-27-CE-23-45-68-3F-E2-89'),
    (4,'00001c55-aab3-4df8-a07e-8eac162fa075','3','18355'),
    (5,'00001c55-aab3-4df8-a07e-8eac162fa075','4','94-3C-84-B1-6A-AA-FD-25-F1-C0-D2-43-CD-D3-57-D6'),
    (6,'00001c55-aab3-4df8-a07e-8eac162fa075','5','Created by C# mass import'),
    (7,'00002205-00D3-4495-B65A-A7B1FD2AE7F2','TITLE','Mass Import 1494780'),
    (8,'00002205-00D3-4495-B65A-A7B1FD2AE7F2','1','00002205-00D3-4495-B65A-A7B1FD2AE7F2'),
    (9,'00002205-00D3-4495-B65A-A7B1FD2AE7F2','2','870386312'),
    (10,'00002205-00D3-4495-B65A-A7B1FD2AE7F2','3','1494780'),
    (11,'00002205-00D3-4495-B65A-A7B1FD2AE7F2','4','-1929051324'),
    (13,'00002342-6de0-4110-b576-fd32f96b2858','TITLE','Mass Import 387008'),
    (14,'00002342-6de0-4110-b576-fd32f96b2858','1','00002342-6de0-4110-b576-fd32f96b2858'),
    (15,'00002342-6de0-4110-b576-fd32f96b2858','2','B0-CB-DF-ED-48-DC-C4-E8-B0-6F-1B-1D-81-2D-6D-51'),
    (16,'00002342-6de0-4110-b576-fd32f96b2858','3','387008')

查找唯一列

DECLARE @cols VARCHAR(MAX)
;WITH CTE
AS
(
    SELECT
        ROW_NUMBER() OVER(PARTITION BY Table1.FieldId 
                              ORDER BY Table1.FieldId) AS RowNbr,
        Table1.*
    FROM
        Table1
)
SELECT @cols=STUFF
(
    (
        SELECT 
            ',' +QUOTENAME(CTE.FieldId)
        FROM
            CTE
        WHERE
            CTE.RowNbr=1
        ORDER BY 
            LEN(CTE.FieldId) DESC,
            CTE.FieldId
        FOR XML PATH('')
    )
,1,1,'')

我们需要订购,以便TITLE排在第一位。 FOR XML PATH是连接列。

动态支点

DECLARE @query NVARCHAR(4000)=
N'SELECT
    *
FROM
(
    SELECT
        Table1.DocumentKey,
        Table1.FieldId,
        Table1.FieldValue
    FROM
        Table1
) AS p
PIVOT
(
    MAX(FieldValue)
    FOR FieldId IN('+@cols+')
) AS p'
EXECUTE(@query)

自我清理(不需要)

DROP TABLE Table1