T-SQL数据透视指南

时间:2011-05-05 13:02:53

标签: sql sql-server database tsql

我在t-sql中有一个表函数,它根据作业号返回3个条目中的拆分值。例如,典型的回报是

JobNumber SplitValue
J1         X1
J1         X2
J1         X3
J2         X1
J2         X2
J2         X3
行中的

返回。

但是,我想要做的是转动结果集,以便我有

J1 X1 X2 X3 
J2 X1 X2 X3

有人可以帮忙吗?

干杯

4 个答案:

答案 0 :(得分:2)

数据透视表最初可能有点难以使用,但对于简单的数据集,它们可能非常强大。

Select [J1],[J2],...
from (
 select JobNumber, SplitValue from tablename
) as sourcetable
PIVOT (
 Max(SplitValue) for JobNumber in ([J1],[J2],...)
) as PivotTable

不幸的是,这也意味着如果不使用动态SQL,则必须对列进行硬编码。查看Pivot and Unpivot tables上的MSDN参考。

答案 1 :(得分:0)

您的数据样本很难理解,因为它看起来非常通用。正如Tim所说,SQL Server的版本会有所帮助。

这是一个版本无关的查询,它提供了请求的输出:

    DECLARE @A Table
(JobNumber varchar(2), SplitValue varchar(2))

INSERT INTO @A
SELECT 'J1', 'X1' UNION ALL
SELECT 'J1',  'X2' UNION ALL
SELECT 'J1',  'X3' UNION ALL
SELECT 'J2',  'X1' UNION ALL
SELECT 'J2', 'X2' UNION ALL
SELECT 'J2', 'X3'    
    SELECT JobNumber
        ,(SELECT 'X1') as [X1]
        ,(SELECT 'X2') as [X2]
        ,(SELECT 'X3') as [X3]
    FROM @A
    GROUP BY JobNumber

但是我不相信它会有很多现实世界的帮助,除了向您展示如何使用子查询构建一个数据透视图。更好的数据=更好的例子。

答案 2 :(得分:0)

这是我解决你的问题的解决方案。没有评论或任何我害怕的事情,但希望这给你一个起点。

使用这样的起始表#Jobs

JobNumber SplitValue
--------- ----------
J1        X1
J1        X2
J1        X3
J2        X1
J2        X2
J2        X3

你得到一个输出:

JobNumber col_0 col_1 col_2
--------- ----- ----- -----
J1        X1    X2    X3
J2        X1    X2    X3

<强>代码:

CREATE TABLE #Jobs
(
    JobNumber varchar(2),
    SplitValue varchar(2)
)

INSERT INTO #Jobs (JobNumber, SplitValue) VALUES ('J1','X1')
INSERT INTO #Jobs (JobNumber, SplitValue) VALUES ('J1','X2')
INSERT INTO #Jobs (JobNumber, SplitValue) VALUES ('J1','X3')
INSERT INTO #Jobs (JobNumber, SplitValue) VALUES ('J2','X1')
INSERT INTO #Jobs (JobNumber, SplitValue) VALUES ('J2','X2')
INSERT INTO #Jobs (JobNumber, SplitValue) VALUES ('J2','X3')

SELECT * FROM #Jobs

DECLARE @ColumnsNeeded int

;WITH CountsTable AS
(
    SELECT COUNT(*) AS ColumnCount FROM #Jobs GROUP BY JobNumber
)
SELECT @ColumnsNeeded = MAX(ColumnCount) FROM CountsTable

DECLARE @Counter int
SET @Counter = 0

CREATE TABLE #Pivoted
(
    JobNumber varchar(2)
)
DECLARE @AddColumnCommandPre varchar(255)
DECLARE @AddColumnCommandPost varchar(255)
DECLARE @AddColumnCommand varchar(255)

SET @AddColumnCommandPre = 'ALTER TABLE #Pivoted ADD col_'
SET @AddColumnCommandPost = ' varchar(2)'

WHILE (@Counter < @ColumnsNeeded)
BEGIN
    SET @AddColumnCommand = @AddColumnCommandPre + CAST(@Counter as varchar(3)) + @AddColumnCommandPost
EXECUTE (@AddColumnCommand)
    SELECT @Counter = @Counter + 1
END

SELECT * INTO #JobsWithRowNum FROM #Jobs
ALTER TABLE #JobsWithRowNum ADD RowNum int IDENTITY(1,1)

CREATE CLUSTERED INDEX JobsWithRowNum_RowNum ON #JobsWithRowNum(RowNum)

DECLARE @RowCount int
SELECT @RowCount = COUNT(*) FROM #JobsWithRowNum

DECLARE @RowInsert varchar(255), @Columns varchar(255), @Data varchar(255)
DECLARE @LastJobNumber varchar(3), @CurrentJobNumber varchar(3)
DECLARE @ColumnCounter int

SET @RowInsert = 'INSERT INTO #Pivoted (JobNumber'
SET @Columns = ''
SELECT @LastJobNumber = JobNumber FROM #JobsWithRowNum WHERE RowNum = 1
SET @Data = ') VALUES (''' + @LastJobNumber

SET @Counter = 1
SET @ColumnCounter = 0
WHILE (@Counter <= @RowCount)
BEGIN
    SELECT @CurrentJobNumber = JobNumber FROM #JobsWithRowNum WHERE RowNum = @Counter
    IF @CurrentJobNumber <> @LastJobNumber
    BEGIN
        EXEC (@RowInsert + @Columns + @Data + ''')')
        SET @Data = ') VALUES (''' + @CurrentJobNumber
        SET @LastJobNumber = @CurrentJobNumber
        SET @ColumnCounter = 0
        SET @Columns = ''
    END

    SET @Columns = @Columns + ', col_' + CAST(@ColumnCounter AS varchar(3))
    SELECT @Data = @Data + ''', ''' + SplitValue FROM #JobsWithRowNum WHERE RowNum = @Counter

    SET @Counter = @Counter + 1
    SET @ColumnCounter = @ColumnCounter + 1
END

EXEC (@RowInsert + @Columns + @Data + ''')')

SELECT * FROM #Pivoted

DROP TABLE #JobsWithRowNum
DROP TABLE #Pivoted
DROP TABLE #Jobs

答案 3 :(得分:0)

试试这个:

示例数据

select * into #tmp from (
    select 'J1' [JobNumber], 'X1' [SplitValue] union all
    select 'J1', 'X2' union all
    select 'J1', 'X3' union all
    select 'J2', 'X1' union all
    select 'J2', 'X2' union all
    select 'J2', 'X3') as t;

JobNumber SplitValue
J1         X1
J1         X2
J1         X3
J2         X1
J2         X2
J2         X3

<强>查询

select [JobNumber], [X1] [col1], [X2] [col2], [X3] [col3]
from #tmp
pivot (
    max([SplitValue])
    for [SplitValue] in ([X1], [X2], [X3])
) as t

JobNumber   col1    col2    col3
J1          X1      X2      X3
J2          X1      X2      X3

<强> SQL Fiddle