SQL Pivot函数

时间:2013-08-14 07:06:47

标签: sql sql-server sql-server-2008 tsql

请帮我编写一个选择查询,使用如下所示透视我的表

我的表结构

enter image description here

并且需要结果结构

  

StoryLineID PlotID StoryLine问题

 1          1      01      question 1
 1          1      02      question 2
 1          1      03      question 3
 1          1      04      question 4
 1          1      05      question 5

2 个答案:

答案 0 :(得分:3)

试试这个 -

DECLARE @temp TABLE
(
      ID INT
    , PlotID INT
    , StoryLine_01 VARCHAR(10)
    , StoryLine_02 VARCHAR(10)
    , StoryLine_03 VARCHAR(10)
    , StoryLine_04 VARCHAR(10)
    , StoryLine_05 VARCHAR(10)
)

INSERT INTO @temp
VALUES 
    (1, 3, 'Q1', 'Q2', 'Q3', 'Q4', 'Q5'),
    (2, 4, 'Q1', 'Q2', 'Q3', 'Q4', 'Q5')

SELECT 
      ID
    , PlotID
    , StoryLine = RIGHT(StoryLine, 2)
    , Question
FROM @temp
UNPIVOT 
(
    Question FOR StoryLine IN (
        StoryLine_01, StoryLine_02, 
        StoryLine_03, StoryLine_04, 
        StoryLine_05
    )
) unpvt

更新(列的动态计数):

IF OBJECT_ID (N'dbo.temp') IS NOT NULL
   DROP TABLE dbo.temp

CREATE TABLE dbo.temp
(
      ID INT
    , PlotID INT              , StoryLine_01 VARCHAR(10)
    , StoryLine_02 VARCHAR(10), StoryLine_03 VARCHAR(10)
    , StoryLine_04 VARCHAR(10), StoryLine_05 VARCHAR(10)
)

INSERT INTO dbo.temp
VALUES (1, 3, 'Q1', 'Q2', 'Q3', 'Q4', 'Q5'), (2, 4, 'Q1', 'Q2', 'Q3', 'Q4', 'Q5')

DECLARE @SQL NVARCHAR(MAX)
SELECT @SQL = '
    SELECT 
          ID
        , PlotID
        , StoryLine = RIGHT(StoryLine, 2)
        , Question
    FROM dbo.temp
    UNPIVOT (
        Question FOR StoryLine IN (
            ' + STUFF((
                SELECT ', ' + name
                FROM sys.columns WITH(NOWAIT)
                WHERE [object_id] = OBJECT_ID('dbo.temp')
                    AND name LIKE 'StoryLine_%'
                FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 2, '') + 
        ')
    ) unpvt'

EXEC sys.sp_executesql @SQL

输出 -

ID          PlotID      StoryLine Question
----------- ----------- --------- ----------
1           3           01        Q1
1           3           02        Q2
1           3           03        Q3
1           3           04        Q4
1           3           05        Q5
2           4           01        Q1
2           4           02        Q2
2           4           03        Q3
2           4           04        Q4
2           4           05        Q5

答案 1 :(得分:2)

如果列数很大且总行数不是很大,则可以执行此常规查询,因此无法明确指定所有列名

;with CTE1 as (
    select ID, PlotID, (select t.* for xml raw('row'), type) as Data
    from @temp as t
), CTE2 as (
    select
         C.ID, C.PlotID,
         F.C.value('local-name(.)', 'nvarchar(128)') as StoryLine,
         F.C.value('.', 'nvarchar(max)') as Question
    from CTE1 as c
        outer apply c.Data.nodes('row/@*') as F(C)
)
select
   ID, PlotID, replace(StoryLine, 'StoryLine_', '') as StoryLine, Question
from CTE2
where StoryLine like 'StoryLine[_]%'

sql fiddle demo(谢谢@Devart!)