在sql中将列值数据转换为行值数据[重复]

问题描述 投票:0回答:2

我有一个在 sql server 中生成以下结果的查询。并且需要将数据从 4 行转置为单行。

当我尝试使用 pivot 函数和 case 语句再次获取 4 行的空值时。请帮助我获得它的想法。

ID  No  Name Letter Answer CMT
123 103 A1    A      Low    Abc
123 103 A2    B      High   Abc
123 103 A3    A      Medium Cde
123 103 A4    C      Low    Hhj 

预期的O / P:

ID No Name1 Letter1 Answe1 CMT1 Name2 Letter2 Ans2 Cmt2 Name3 Letter3 ans3 cmt3 name4 letter4 ans4 cmt4
123 103 A1 A Low Abc A2 B High Abc A3 A Medium Cde A4 C Low Hhj
sql sql-server pivot dynamic-sql
2个回答
0
投票
WITH myData AS 
(
    SELECT ID,
           No,
           Name,
           Letter,
           Answer,
           CMT,
           ROW_NUMBER() OVER (PARTITION BY Id,No ORDER BY ID, No) rn
           FROM myTable
) 
SELECT ID,
       No,
       MAX(CASE WHEN rn = 1 THEN Name END) name1,
       MAX(CASE WHEN rn = 1 THEN Letter END) Letter1,
       MAX(CASE WHEN rn = 1 THEN Answer END) Answer1,
       MAX(CASE WHEN rn = 1 THEN CMT END) CMT1,
       MAX(CASE WHEN rn = 2 THEN Name END) name2,
       MAX(CASE WHEN rn = 2 THEN Letter END) Letter2,
       MAX(CASE WHEN rn = 2 THEN Answer END) Answer2,
       MAX(CASE WHEN rn = 2 THEN CMT END) CMT2,
       MAX(CASE WHEN rn = 3 THEN Name END) name3,
       MAX(CASE WHEN rn = 3 THEN Letter END) Letter3,
       MAX(CASE WHEN rn = 3 THEN Answer END) Answer3,
       MAX(CASE WHEN rn = 3 THEN CMT END) CMT3,
       MAX(CASE WHEN rn = 4 THEN Name END) name4,
       MAX(CASE WHEN rn = 4 THEN Letter END) Letter4,
       MAX(CASE WHEN rn = 4 THEN Answer END) Answer4,
       MAX(CASE WHEN rn = 4 THEN CMT END) CMT4
       FROM myData
       GROUP BY Id, No;
ID 没有 姓名1 字母1 回答1 CMT1 姓名2 字母2 答案2 CMT2 姓名3 字母3 答案3 CMT3 姓名4 字母4 回答4 CMT4
123 103 A1 A Abc A2 Abc A3 A 中等 Cde A4 C Hhj

DBfiddle 演示


0
投票

我不建议使用“pivot”来满足这种需求。虽然这乍一看可能很复杂,但使用“条件聚合”(聚合函数内的 case 表达式)实现输出会更容易:

SELECT
      ID
    , No
    , MAX(CASE WHEN Name = 'A1' THEN Name END) AS Name1
    , MAX(CASE WHEN Name = 'A1' THEN Letter END) AS Letter1
    , MAX(CASE WHEN Name = 'A1' THEN Answer END) AS Answer1
    , MAX(CASE WHEN Name = 'A1' THEN CMT END) AS CMT1
    , MAX(CASE WHEN Name = 'A2' THEN Name END) AS Name2
    , MAX(CASE WHEN Name = 'A2' THEN Letter END) AS Letter2
    , MAX(CASE WHEN Name = 'A2' THEN Answer END) AS Answer2
    , MAX(CASE WHEN Name = 'A2' THEN CMT END) AS CMT2
    , MAX(CASE WHEN Name = 'A3' THEN Name END) AS Name3
    , MAX(CASE WHEN Name = 'A3' THEN Letter END) AS Letter3
    , MAX(CASE WHEN Name = 'A3' THEN Answer END) AS Answer3
    , MAX(CASE WHEN Name = 'A3' THEN CMT END) AS CMT3
    , MAX(CASE WHEN Name = 'A4' THEN Name END) AS Name4
    , MAX(CASE WHEN Name = 'A4' THEN Letter END) AS Letter4
    , MAX(CASE WHEN Name = 'A4' THEN Answer END) AS Answer4
    , MAX(CASE WHEN Name = 'A4' THEN CMT END) AS CMT4
FROM mytable
GROUP BY
      ID
    , No

;

对于动态sql:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX),
    @colNames AS NVARCHAR(MAX);

SET @cols = STUFF((SELECT DISTINCT ',' +
                        'MAX(CASE WHEN Name = ''' + Name + ''' THEN Name END) AS Name' + Name + ',' +
                        'MAX(CASE WHEN Name = ''' + Name + ''' THEN Letter END) AS Letter' + Name + ',' +
                        'MAX(CASE WHEN Name = ''' + Name + ''' THEN Answer END) AS Answer' + Name + ',' +
                        'MAX(CASE WHEN Name = ''' + Name + ''' THEN CMT END) AS CMT' + Name
                    FROM mytable
                    FOR XML PATH(''), TYPE
                    ).value('.', 'NVARCHAR(MAX)'),1,1,'')

SET @colNames = STUFF((SELECT DISTINCT ',' +
                            'Name' + Name + ',Letter' + Name + ',Answer' + Name + ',CMT' + Name
                        FROM mytable
                        FOR XML PATH(''), TYPE
                        ).value('.', 'NVARCHAR(MAX)'),1,1,'')

SET @query = 'SELECT ID, No,' + @cols +
             ' FROM mytable GROUP BY ID, No'

EXECUTE(@query);
ID 没有 姓名A1 字母A1 答案A1 CMTA1 姓名A2 字母A2 答案A2 CMTA2 姓名A3 字母A3 答案A3 CMTA3 姓名A4 字母A4 答案A4 CMTA4
123 103 A1 A Abc A2 Abc A3 A 中等 Cde A4 C Hhj

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.