在SQL中反转列和行

时间:2019-01-30 08:31:05

标签: sql sql-server tsql pivot sql-server-2016

我必须创建查询,以反转行和列的正确性。我正在使用MS SQL SERVER 2016。

这就是我所拥有的:

Row_ID | Group_ID | Group_Status | MemberRole | name
2807   | 10568    | accept       | chairman   | Rajah
2808   | 10568    | accept       | member     | Vaughan
2812   | 10568    | accept       | secretary  | Susan

这就是我需要的:

Group_ID | Status | Chairman | Secretary | Member1 | Member2 | Member3 | ... | Member20 
10568    | Accept | Rajah    | Susan     | Vaughan | Kane    | Oprah   | ... | Imelda

(具有成员角色的用户可以在0到20之间)

可能我应该使用数据透视,但是我不知道如何使用。

好,我有以下代码:

 SELECT *
FROM
(
    SELECT group_id, 
       group_status, 
       memberRole, 
       name
FROM DataGroup
) dataSource PIVOT(MAX(name) FOR memberRole IN([chairman], 
                                           [secretary], 
                                           [member])) pivotTab;

但是我丢失了带有成员的行(仅获得一个成员),如何将它们提取到列中?

2 个答案:

答案 0 :(得分:2)

您可以使用 unioned 查询尝试此操作:

一些模型(请在下一个问题中自行提供带有样本数据的虚拟表)

DECLARE @mockup TABLE(Row_ID INT,Group_ID INT,Group_Status VARCHAR(100),MemberRole VARCHAR(100),[name] VARCHAR(100));
INSERT INTO @mockup VALUES
 (2807,10568,'accept','chairman','Rajah')
,(2808,10568,'accept','member','Vaughan')
,(2812,10568,'accept','secretary','Susan')
,(2899,10568,'accept','member','Onemore');

-查询

SELECT p.*
FROM
(
    SELECT Group_ID
          ,Group_Status
          ,[name]
          ,MemberRole
    FROM @mockup 
    WHERE MemberRole IN('chairman','secretary')

    UNION ALL
    SELECT Group_ID
          ,Group_Status
          ,[name]
          ,CONCAT('Member',ROW_NUMBER() OVER(PARTITION BY Group_ID ORDER BY Row_ID))  
    FROM @mockup 
    WHERE MemberRole='member'
) t
PIVOT
(
    MAX([name]) FOR MemberRole IN(Chairman,Secretary,Member1,Member2,Member3 /*add as many as you need*/)
) p;

结果

Group_ID    Group_Status    Chairman    Secretary   Member1     Member2     Member3
10568       accept          Rajah       Susan       Vaughan     Onemore     NULL

简而言之:

查询的第一部分将只选择两个修订名称。

第二部分将选择成员并按其Row_ID对其编号。

然后,PIVOT会将其转换为单行,并使用列MemberRole作为新列的名称。

您将不得不考虑更多事情:

  • 如果不是所有行都是accepted,怎么办?
  • 有多少个小组?

如果需要帮助,可以提出一个新问题。祝您编码愉快!

答案 1 :(得分:1)

我只使用条件聚合:

select group_id, group_status,
       max(case when member_role = 'chairman' then name end) as chairman,
       max(case when member_role = 'secretary' then name end) as secretary,
       max(case when member_role = 'member' and seqnum = 1 then name end) as member_01,
       max(case when member_role = 'member' and seqnum = 2 then name end) as member_02,
       . . .
from (select m.*,
             row_number() over (partition by group_id, member_role order by row_id) as seqnum
      from @mockup m
     ) m
group by group_id, group_status;

我发现条件聚合比pivot更灵活。这是查询更简单的一种情况。