MS SQL 旋转另一个 Table 多次

MS SQL Pivot Another Table Multiple Times

我有一个具有以下结构的数据库

ID   Name
1     John
2     Doe
3     Dave
4     Smith

另一个table持有员工亲属

ID EmpID RelativeType Name
1  1      Son         x
2  1      Daughter    y
3  1      Wife        a
4  1      Friend      b
5  1      Father      c
6  1      Friend      e

孩子最多可以固定8个,朋友最多可以固定3个

我能够在下面进行数据透视查询以带孩子,但无法再次进行数据透视以获取 3 个朋友、父亲等。

这是我的查询:

    select *
from 
(
  select e.ID, e.FirstName,
  CASE WHEN es.RelativeType = 'Son' or es.RelativeType = 'Daughter' THEN es.FirstName END as Child, CASE WHEN es.RelativeType = 'Son' or es.RelativeType = 'Daughter' THEN CONCAT('Child ',ROW_NUMBER() OVER (ORDER BY e.ID)) END as Relation
  from Employee e
  left join EmployeeRelatives es
    on e.ID = es.EmpID
  group by 
 e.ID, e.FirstName,es.RelativeID,es.FirstName
) x
pivot
(
  max(Child)
  for Relation in([Child 1],[Child 2],[Child 3], [Child 4], [Child 5], [Child 6], [Child 7], [Child 8])
) as p1

以上查询returns结果如下。

EmpID , Name, Child 1, Child 2,Child 3, Child 4, Child 5, Child 6
 1      John   x        y       NULL    NULL     NULL     NULL

当我制作多个支点时,它 returns 多行,这不是必需的。 我需要修改上面的查询以带来想要的结果

需要的结果集如下

EmpID , Name, Child 1, Child 2, Child 3, Child 4, Wife, Friend 1, Friend 2, Friend 3, Father
 1      John   x        y         NULL    NULL      a      b        e          NULL       c

我正在使用 MS SQL 2014.

我在这里使用了所谓的 "CROSS PIVOT"。

就像我说的,这不太好;你真的应该在你的表现层这样做。该解决方案不可扩展,而且维护起来可能很痛苦。无论如何,这里是:

CREATE TABLE #Employee (ID int, [Name] varchar(10));

INSERT INTO #Employee
VALUES(1,'John'),
      (2,'Doe'),
      (3,'Dave'),
      (4,'Smith');

CREATE TABLE #Relative (ID int, EmpID int, RelativeType varchar(10), [Name] char(1)); 
INSERT INTO #Relative
VALUES(1,1,'Son','x'),
      (2,1,'Daughter','y'),
      (3,1,'Wife','a'),
      (4,1,'Friend','b'),
      (5,1,'Father','c'),
      (6,1,'Friend','e');

WITH RNs AS (
    SELECT *,
           CASE RelativeType WHEN 'Son' THEN 'Child'
                             WHEN 'Daughter' THEN 'Child'
                             WHEN 'Mother' THEN 'Parent'
                             WHEN 'Father' THEN 'Parent'
                             WHEN 'Wife' THEN 'Spouse'
                             WHEN 'Husband' THEN 'Spouse'
                             ELSE RelativeType END AS Relation,
           ROW_NUMBER() OVER (PARTITION BY EmpID,
                                           CASE RelativeType WHEN 'Son' THEN 'Child'
                                                             WHEN 'Daughter' THEN 'Child'
                                                             WHEN 'Mother' THEN 'Parent'
                                                             WHEN 'Father' THEN 'Parent'
                                                             WHEN 'Wife' THEN 'Spouse'
                                                             WHEN 'Husband' THEN 'Spouse'
                                                             ELSE RelativeType END
                              ORDER BY ID ASC) RN
    FROM #Relative R)

SELECT E.ID AS EmpID,
       E.[Name],
       MAX(CASE WHEN R.Relation = 'Child' AND RN = 1 THEN R.[Name] END) AS Child1,
       MAX(CASE WHEN R.Relation = 'Child' AND RN = 2 THEN R.[Name] END) AS Child2,
       MAX(CASE WHEN R.Relation = 'Child' AND RN = 3 THEN R.[Name] END) AS Child3,
       MAX(CASE WHEN R.Relation = 'Child' AND RN = 4 THEN R.[Name] END) AS Child4,
       MAX(CASE WHEN R.Relation = 'Child' AND RN = 5 THEN R.[Name] END) AS Child5,
       MAX(CASE WHEN R.Relation = 'Child' AND RN = 6 THEN R.[Name] END) AS Child6,
       MAX(CASE WHEN R.Relation = 'Child' AND RN = 7 THEN R.[Name] END) AS Child7,
       MAX(CASE WHEN R.Relation = 'Child' AND RN = 8 THEN R.[Name] END) AS Child8,
       MAX(CASE WHEN R.Relation = 'Spouse' AND RN = 1 THEN R.[Name] END) AS Spouse,
       MAX(CASE WHEN R.Relation = 'Friend' AND RN = 1 THEN R.[Name] END) AS Friend1,
       MAX(CASE WHEN R.Relation = 'Friend' AND RN = 2 THEN R.[Name] END) AS Friend2,
       MAX(CASE WHEN R.Relation = 'Friend' AND RN = 3 THEN R.[Name] END) AS Friend3
       --You get the idea
FROM #Employee E
     JOIN RNs R ON E.ID = R.EmpID
GROUP BY E.ID,
         E.[Name];

GO
DROP TABLE #Employee;
DROP TABLE #Relative;

你可以试试看,希望对你有帮助:) 祝你好运!! :)

WITH Children AS
(
    SELECT e.EmpID, e.FirstName EmpName, er.FirstName RelName,
            'Child' + CONVERT(NVARCHAR(2), ROW_NUMBER() OVER (PARTITION BY er.EmpID ORDER BY er.RelativeID)) AS 'Relation'
    FROM Employee e
    LEFT JOIN EmployeeRelatives er ON e.EmpID = er.EmpID
    WHERE er.RelativeType IN ('Son', 'Daughter')
),
ChildInRow AS
(
    SELECT *
    FROM Children
    PIVOT
    (
      MAX(RelName)
      FOR Relation in([Child1],[Child2],[Child3], [Child4], [Child5], [Child6], [Child7], [Child8])
    ) AS p1
),
Friends AS
(
    SELECT e.EmpID, e.FirstName EmpName, er.FirstName RelName,
            'Friend' + CONVERT(NVARCHAR(2), ROW_NUMBER() OVER (PARTITION BY er.EmpID ORDER BY er.RelativeID)) AS 'Relation'
    FROM Employee e
    LEFT JOIN EmployeeRelatives er ON e.EmpID = er.EmpID
    WHERE er.RelativeType = 'Friend'
),
FriendsInRow AS
(
    SELECT *
    FROM Friends
    PIVOT
    (
      MAX(RelName)
      FOR Relation in([Friend1],[Friend2],[Friend3])
    ) AS p1
),
AllWife AS
(
    SELECT e.EmpID, e.FirstName EmpName, er.FirstName RelName, 'Wife' AS 'Relation',
            ROW_NUMBER() OVER (PARTITION BY er.EmpID ORDER BY er.RelativeID) wife_row_num
    FROM Employee e
    LEFT JOIN EmployeeRelatives er ON e.EmpID = er.EmpID
    WHERE er.RelativeType = 'Wife'
),
WifeInRow AS
(
    SELECT * FROM AllWife WHERE wife_row_num = 1
),
AllFather AS
(
    SELECT e.EmpID, e.FirstName EmpName, er.FirstName RelName, 'Father' AS 'Relation',
            ROW_NUMBER() OVER (PARTITION BY er.EmpID ORDER BY er.RelativeID) father_row_num
    FROM Employee e
    LEFT JOIN EmployeeRelatives er ON e.EmpID = er.EmpID
    WHERE er.RelativeType = 'Father'
),
FatherInRow AS
(
    SELECT * FROM AllFather WHERE father_row_num = 1
)
SELECT e.EmpID, e.FirstName,
        ISNULL(Child1, '') Child1, ISNULL(Child2, '') Child2, ISNULL(Child3, '') Child3, ISNULL(Child4, '') Child4, ISNULL(Child5, '') Child5, ISNULL(Child6, '') Child6, ISNULL(Child7, '') Child7, ISNULL(Child8, '') Child8,
        ISNULL(w.RelName, '') Wife,
        ISNULL(Friend1, '') Friend1, ISNULL(Friend2, '') Friend2, ISNULL(Friend3, '') Friend3,
        ISNULL(fa.RelName, '') Father
FROM Employee e
FULL OUTER JOIN ChildInRow c ON e.EmpID = c.EmpID
FULL OUTER JOIN FriendsInRow f ON e.EmpID = f.EmpID
FULL OUTER JOIN WifeInRow w ON e.EmpID = w.EmpID
FULL OUTER JOIN FatherInRow fa ON e.EmpID = fa.EmpID

结果应该是这样的: