Sql 联接表并全部联合/透视/取消Pivot?

Sql 联接表并全部联合/透视/取消Pivot?,sql,sql-server,sql-server-2008,tsql,join,Sql,Sql Server,Sql Server 2008,Tsql,Join,我在数据库中有四个表,如下所示: 表1:员工详细信息 ----------------------------------------------------------------------- | Employee ID | Name | Department |DateofJoining | ----------------------------------------------------------------------- | | |

我在数据库中有四个表,如下所示:

表1:员工详细信息

-----------------------------------------------------------------------
| Employee ID | Name  | Department |DateofJoining |
-----------------------------------------------------------------------
|             |       |            |              |
| e1          | name1 | d1         | date1        |
| e2          | name2 | d2         | date2        |
| e3          | name3 | d3         | date3        |
-----------------------------------------------------------------------
-----------------------------------------------------------------------
| EmployeeID | CertificationID |  Name  |
-----------------------------------------------------------------------
|            |                 |        |
| e1         | c1              | cname1 |
| e1         | c2              | cname2 |
| e2         | c3              | cname3 |
-----------------------------------------------------------------------
----------------------------------------------------------------------------
| EmployeeId | TotalExp | Qualification | Specialization |
----------------------------------------------------------------------------
|            |          |               |                |
| e1         | 1        | q1            | abc            |
| e2         | 2        | q2            | xyz            |
----------------------------------------------------------------------------
表2:员工技能集

----------------------------------------------------------------------------
| EmployeeID | SkillId | SkillName | SkillExperience | SkillRating |
----------------------------------------------------------------------------
|            |         |           |                 |             |
| e1         | s1      | skill1    |               11|           11|
| e1         | s2      | skill2    |               12|           12|
| e1         | s3      | skill3    |               13|           13|
| e2         | s1      | skill1    |               21|           21|
| e2         | s2      | skill2    |               22|           22|
| e2         | s3      | skill3    |               23|           23|
----------------------------------------------------------------------------
表3:员工认证

-----------------------------------------------------------------------
| Employee ID | Name  | Department |DateofJoining |
-----------------------------------------------------------------------
|             |       |            |              |
| e1          | name1 | d1         | date1        |
| e2          | name2 | d2         | date2        |
| e3          | name3 | d3         | date3        |
-----------------------------------------------------------------------
-----------------------------------------------------------------------
| EmployeeID | CertificationID |  Name  |
-----------------------------------------------------------------------
|            |                 |        |
| e1         | c1              | cname1 |
| e1         | c2              | cname2 |
| e2         | c3              | cname3 |
-----------------------------------------------------------------------
----------------------------------------------------------------------------
| EmployeeId | TotalExp | Qualification | Specialization |
----------------------------------------------------------------------------
|            |          |               |                |
| e1         | 1        | q1            | abc            |
| e2         | 2        | q2            | xyz            |
----------------------------------------------------------------------------
表4:其他详细信息

-----------------------------------------------------------------------
| Employee ID | Name  | Department |DateofJoining |
-----------------------------------------------------------------------
|             |       |            |              |
| e1          | name1 | d1         | date1        |
| e2          | name2 | d2         | date2        |
| e3          | name3 | d3         | date3        |
-----------------------------------------------------------------------
-----------------------------------------------------------------------
| EmployeeID | CertificationID |  Name  |
-----------------------------------------------------------------------
|            |                 |        |
| e1         | c1              | cname1 |
| e1         | c2              | cname2 |
| e2         | c3              | cname3 |
-----------------------------------------------------------------------
----------------------------------------------------------------------------
| EmployeeId | TotalExp | Qualification | Specialization |
----------------------------------------------------------------------------
|            |          |               |                |
| e1         | 1        | q1            | abc            |
| e2         | 2        | q2            | xyz            |
----------------------------------------------------------------------------
现在,必须查询上述四个表才能获得如下输出:

+------------+-------+-------------+---------------+---------+----------------+----------------+------------+----------------+--------+--------------+------------------+
| EmployeeID | Name  | Department  | Qualification | Tot_Exp | Specialization | Certifications | Skill1_Exp | Skill1_Rating  | ……………… | Skill100_Exp | Skill100_Rating  |
+------------+-------+-------------+---------------+---------+----------------+----------------+------------+----------------+--------+--------------+------------------+
|            |       |             |               |         |                |                |            |                |        |              |                  |
| e1         | name1 | d1          | q1            | 1       | spec1          | c1,c2          | 11         | 11             | ……………. | …………………      | ………………………        |
| e2         | name2 | d2          | q2            | 2       | spec2          | c3             | 21         | 21             | ……………. | …………………      | ………………………        |
+------------+-------+-------------+---------------+---------+----------------+----------------+------------+----------------+--------+--------------+------------------+
到目前为止,我已经能够对表2-Employee_SkillSet执行一个查询(使用动态SQL),如下所示:

----------------------------------------------------------------------------
| EmpId | S1_Exp | S1_Rating | S2_Exp | S2_Rating | S3_Exp | S3_Rating |....
----------------------------------------------------------------------------
|       |        |           |        |            |       |           |
| e1    | 11     | 11        | 12     | 12         | 13    | 13        |....    
| e2    | 21     | 21        | 22     | 22         | 23    | 23        |....
| e3    | 31     | 31        | 32     | 32         | 33    | 33        |....
----------------------------------------------------------------------------
P.S. S is for Skill which I abbreviated over here  to conserve space 
我的问题是,如何将其他三个表按行连接到此表,以获得所需的输出

我可能应该指出,我对连接、透视/取消透视、交叉应用以及两者之间的一切都很陌生,所以即使答案非常简单,我似乎也无法理解

编辑

创建脚本:

CREATE TABLE Employee_Details ( 
    [Employee ID] nvarchar(2),
    [Name] nvarchar(10),
    Department nvarchar(2),
    DateofJoining nvarchar(5)
)

INSERT INTO Employee_Details VALUES
('e1', 'name1', 'd1', 'date1'),
('e2', 'name2', 'd2', 'date2'),
('e3', 'name3', 'd3', 'date3')

CREATE TABLE Employee_SkillSet (
    EmployeeID nvarchar(2),
    SkillId nvarchar(2),
    SkillName nvarchar(10),
    SkillExperience int,
    SkillRating int
)

INSERT INTO Employee_SkillSet VALUES
('e1', 's1', 'skill1', 11, 11),
('e1', 's2', 'skill2', 12, 12),
('e1', 's3', 'skill3', 13, 13),
('e2', 's1', 'skill1', 21, 21),
('e2', 's2', 'skill2', 22, 22),
('e2', 's3', 'skill3', 23, 23)

CREATE TABLE Employee_Certifications (
    EmployeeID nvarchar(2),
    CertificationID nvarchar(2),
    [Name] nvarchar(10)
)

INSERT INTO Employee_Certifications VALUES
('e1', 'c1', 'cname1'),
('e1', 'c2', 'cname2'),
('e2', 'c3', 'cname3')

CREATE TABLE Other_Details (
    EmployeeId nvarchar(2),
    TotalExp int,
    Qualification nvarchar(2),
    Specialization nvarchar(100)
)

INSERT INTO Other_Details VALUES
('e1', 1, 'q1', 'abc'),
('e2', 2, 'q2', 'xyz')

创建脚本:

您可以使用以下内容,而不是使用动态SQL获取技能:

SELECT      ed.EmployeeID AS EmpID,
            ss1.SkillExperience AS S1_Exp,
            ss1.SkillRating AS S1_Rating,
            ss2.SkillExperience AS S2_Exp,
            ss2.SkillRating AS S2_Rating,
            ss3.SkillExperience AS S3_Exp,
            ss3.SkillRating AS S3_Rating
FROM        Employee_Details ed
INNER JOIN  Employee_SkillSet ss1 ON ed.EmployeeID = ss1.EmployeeID AND ss1.SkillName = 'skill1'
INNER JOIN  Employee_SkillSet ss2 ON ed.EmployeeID = ss2.EmployeeID AND ss2.SkillName = 'skill2'
INNER JOIN  Employee_SkillSet ss3 ON ed.EmployeeID = ss3.EmployeeID AND ss3.SkillName = 'skill2'
现在来完成它

WITH Certifications AS
(
SELECT  EmployeeId
       ,STUFF((SELECT ', ' + CAST(Name AS VARCHAR(10)) [text()]
         FROM Employee_Certifications 
         WHERE EmployeeId = c.EmployeeId
         FOR XML PATH(''), TYPE)
        .value('.','NVARCHAR(MAX)'),1,2,' ') Certifications
FROM Employee_Certifications c
GROUP BY EmployeeId
)

,Skills AS
(
SELECT      ed.EmployeeID AS EmpID,
            ss1.SkillExperience AS S1_Exp,
            ss1.SkillRating AS S1_Rating,
            ss2.SkillExperience AS S2_Exp,
            ss2.SkillRating AS S2_Rating,
            ss3.SkillExperience AS S3_Exp,
            ss3.SkillRating AS S3_Rating
FROM        Employee_Details ed
INNER JOIN  Employee_SkillSet ss1 ON ed.EmployeeID = ss1.EmployeeID AND ss1.SkillName = 'skill1'
INNER JOIN  Employee_SkillSet ss2 ON ed.EmployeeID = ss2.EmployeeID AND ss2.SkillName = 'skill2'
INNER JOIN  Employee_SkillSet ss3 ON ed.EmployeeID = ss3.EmployeeID AND ss3.SkillName = 'skill2'
)

SELECT      ed.EmployeeID,
            ed.Name,
            ed.Department,
            od.Qualification,
            od.TotalExp,
            od.Specialization,
            c.Certifications,
            s.S1_Exp,
            s.S1_Rating,
            s.S2_Exp,
            s.S2_Rating,
            s.S3_Exp,
            s.S3_Rating         
FROM        Employee_Details ed
LEFT JOIN   Other_Details od ON od.EmployeeId = ed.EmployeeId
LEFT JOIN   Certifications c ON c.EmployeeID = ed.EmployeeID
LEFT JOIN   Skills s ON s.EmpID = ed.EmployeeID

您可以使用以下方法,而不是使用动态SQL获取技能:

SELECT      ed.EmployeeID AS EmpID,
            ss1.SkillExperience AS S1_Exp,
            ss1.SkillRating AS S1_Rating,
            ss2.SkillExperience AS S2_Exp,
            ss2.SkillRating AS S2_Rating,
            ss3.SkillExperience AS S3_Exp,
            ss3.SkillRating AS S3_Rating
FROM        Employee_Details ed
INNER JOIN  Employee_SkillSet ss1 ON ed.EmployeeID = ss1.EmployeeID AND ss1.SkillName = 'skill1'
INNER JOIN  Employee_SkillSet ss2 ON ed.EmployeeID = ss2.EmployeeID AND ss2.SkillName = 'skill2'
INNER JOIN  Employee_SkillSet ss3 ON ed.EmployeeID = ss3.EmployeeID AND ss3.SkillName = 'skill2'
现在来完成它

WITH Certifications AS
(
SELECT  EmployeeId
       ,STUFF((SELECT ', ' + CAST(Name AS VARCHAR(10)) [text()]
         FROM Employee_Certifications 
         WHERE EmployeeId = c.EmployeeId
         FOR XML PATH(''), TYPE)
        .value('.','NVARCHAR(MAX)'),1,2,' ') Certifications
FROM Employee_Certifications c
GROUP BY EmployeeId
)

,Skills AS
(
SELECT      ed.EmployeeID AS EmpID,
            ss1.SkillExperience AS S1_Exp,
            ss1.SkillRating AS S1_Rating,
            ss2.SkillExperience AS S2_Exp,
            ss2.SkillRating AS S2_Rating,
            ss3.SkillExperience AS S3_Exp,
            ss3.SkillRating AS S3_Rating
FROM        Employee_Details ed
INNER JOIN  Employee_SkillSet ss1 ON ed.EmployeeID = ss1.EmployeeID AND ss1.SkillName = 'skill1'
INNER JOIN  Employee_SkillSet ss2 ON ed.EmployeeID = ss2.EmployeeID AND ss2.SkillName = 'skill2'
INNER JOIN  Employee_SkillSet ss3 ON ed.EmployeeID = ss3.EmployeeID AND ss3.SkillName = 'skill2'
)

SELECT      ed.EmployeeID,
            ed.Name,
            ed.Department,
            od.Qualification,
            od.TotalExp,
            od.Specialization,
            c.Certifications,
            s.S1_Exp,
            s.S1_Rating,
            s.S2_Exp,
            s.S2_Rating,
            s.S3_Exp,
            s.S3_Rating         
FROM        Employee_Details ed
LEFT JOIN   Other_Details od ON od.EmployeeId = ed.EmployeeId
LEFT JOIN   Certifications c ON c.EmployeeID = ed.EmployeeID
LEFT JOIN   Skills s ON s.EmpID = ed.EmployeeID
您可以使用:

  • 用于XML路径(“”)获取逗号分隔的值
  • 动态SQL,所以如果有新技能出现,您无需更改查询
  • 旋转以将行转换为列
我的解决方案如下:

DECLARE @col nvarchar(max),
        @sql nvarchar(max)

SELECT @col = (
    SELECT DISTINCT ','+QUOTENAME(SkillName + STUFF([name],1,5,'_'))
    FROM Employee_SkillSet es
    CROSS JOIN sys.columns sc
    WHERE sc.[object_id] = OBJECT_ID(N'Employee_SkillSet')
            AND sc.column_id > 3
    FOR XML PATH('')
)
--That will generate the string:
--,[skill1_Experience],[skill1_Rating],[skill2_Experience],[skill2_Rating]...[skillN_Experience],[skillN_Rating]

SELECT @sql= N'
SELECT  ed.EmployeeID,
        ed.[Name],
        ed.Department,
        STUFF((
        SELECT '',''+Qualification
        FROM Other_Details
        WHERE ed.EmployeeID = EmployeeID
        FOR XML PATH('''')
        ),1,1,'''') as Qualification,
        STUFF((
        SELECT '',''+CAST(TotalExp as nvarchar(10))
        FROM Other_Details
        WHERE ed.EmployeeID = EmployeeID
        FOR XML PATH('''')
        ),1,1,'''') as TotalExp,
        STUFF((
        SELECT '',''+Specialization
        FROM Other_Details
        WHERE ed.EmployeeID = EmployeeID
        FOR XML PATH('''')
        ),1,1,'''') as Specialization,
        STUFF((
        SELECT '',''+CertificationID
        FROM Employee_Certifications
        WHERE ed.EmployeeID = EmployeeID
        FOR XML PATH('''')
        ),1,1,'''') as Certification'+@col+'
FROM Employee_Details ed 
LEFT JOIN (
    SELECT *
    FROM (
        SELECT  EmployeeID,
                SkillName + STUFF(Skills,1,5,''_'') as [Columns],
                [Values]
        FROM (
            SELECT *
            FROM Employee_SkillSet
        ) as es
        UNPIVOT (
            [Values] FOR Skills IN (SkillExperience,SkillRating)
        ) unp
    ) as s
    PIVOT (
        MAX([Values]) FOR [Columns] IN ('+STUFF(@col,1,1,'')+')
    ) pvt
) as f
    ON f.EmployeeID = ed.EmployeeID'

EXEC sp_executesql @sql
输出:

EmployeeID  Name    Department  Qualification   TotalExp    Specialization  Certification   skill1_Experience   skill1_Rating   skill2_Experience   skill2_Rating   skill3_Experience   skill3_Rating
e1          name1   d1          q1              1           abc             c1,c2           11                  11              12                  12              13                  13
e2          name2   d2          q2              2           xyz             c3              21                  21              22                  22              23                  23
e3          name3   d3          NULL            NULL        NULL            NULL            NULL                NULL            NULL                NULL            NULL                NULL
注意:我在UNPIVOT部分使用
SkillExperience,SkillRating
,如果有更多的技能属性,那么您可以使用另一个变量,如
@col
来传递逗号分隔的值。

您可以使用:

  • 用于XML路径(“”)获取逗号分隔的值
  • 动态SQL,所以如果有新技能出现,您无需更改查询
  • 旋转以将行转换为列
我的解决方案如下:

DECLARE @col nvarchar(max),
        @sql nvarchar(max)

SELECT @col = (
    SELECT DISTINCT ','+QUOTENAME(SkillName + STUFF([name],1,5,'_'))
    FROM Employee_SkillSet es
    CROSS JOIN sys.columns sc
    WHERE sc.[object_id] = OBJECT_ID(N'Employee_SkillSet')
            AND sc.column_id > 3
    FOR XML PATH('')
)
--That will generate the string:
--,[skill1_Experience],[skill1_Rating],[skill2_Experience],[skill2_Rating]...[skillN_Experience],[skillN_Rating]

SELECT @sql= N'
SELECT  ed.EmployeeID,
        ed.[Name],
        ed.Department,
        STUFF((
        SELECT '',''+Qualification
        FROM Other_Details
        WHERE ed.EmployeeID = EmployeeID
        FOR XML PATH('''')
        ),1,1,'''') as Qualification,
        STUFF((
        SELECT '',''+CAST(TotalExp as nvarchar(10))
        FROM Other_Details
        WHERE ed.EmployeeID = EmployeeID
        FOR XML PATH('''')
        ),1,1,'''') as TotalExp,
        STUFF((
        SELECT '',''+Specialization
        FROM Other_Details
        WHERE ed.EmployeeID = EmployeeID
        FOR XML PATH('''')
        ),1,1,'''') as Specialization,
        STUFF((
        SELECT '',''+CertificationID
        FROM Employee_Certifications
        WHERE ed.EmployeeID = EmployeeID
        FOR XML PATH('''')
        ),1,1,'''') as Certification'+@col+'
FROM Employee_Details ed 
LEFT JOIN (
    SELECT *
    FROM (
        SELECT  EmployeeID,
                SkillName + STUFF(Skills,1,5,''_'') as [Columns],
                [Values]
        FROM (
            SELECT *
            FROM Employee_SkillSet
        ) as es
        UNPIVOT (
            [Values] FOR Skills IN (SkillExperience,SkillRating)
        ) unp
    ) as s
    PIVOT (
        MAX([Values]) FOR [Columns] IN ('+STUFF(@col,1,1,'')+')
    ) pvt
) as f
    ON f.EmployeeID = ed.EmployeeID'

EXEC sp_executesql @sql
输出:

EmployeeID  Name    Department  Qualification   TotalExp    Specialization  Certification   skill1_Experience   skill1_Rating   skill2_Experience   skill2_Rating   skill3_Experience   skill3_Rating
e1          name1   d1          q1              1           abc             c1,c2           11                  11              12                  12              13                  13
e2          name2   d2          q2              2           xyz             c3              21                  21              22                  22              23                  23
e3          name3   d3          NULL            NULL        NULL            NULL            NULL                NULL            NULL                NULL            NULL                NULL

注意:我在UNPIVOT部分使用了
SkillExperience,SkillRating
,如果有更多的技能属性,那么你可以使用另一个变量,比如
@col
来传递逗号分隔的值。

这不就是empID上的连接吗?您可能只需要一个类似STUFF FOR XML PATH(“”)的语句来连接列(例如,证书)。是的,它是EmpId上的连接。我搞不清楚的是如何透视结果表,使与一个EmpID对应的所有数据都在一行中,这不只是EmpID上的一个连接吗?您可能只需要一个类似STUFF FOR XML PATH(“”)的语句来连接列(例如,证书)。是的,它是EmpId上的连接。我搞不清楚的是如何透视结果表,以便与一个EmpID对应的所有数据都在一行中。我之所以使用动态sql,是因为这些技能超过100项。为所有100个技能ID显式添加数据是不行的。我之所以使用动态sql是因为技能超过100个。为所有100个技能ID显式添加数据是行不通的。谢谢……这看起来很有希望,查询与我尝试实现的类似。现在,我将运行实际表的查询,并查看得到的结果。我得到一个错误:列名“EmployeeID”无效。我认为这是表描述中的一个输入错误。将查询中的
ed.EmployeeId
更改为
ed.[Employee ID]
。这样做了。工作得很有魅力。你是救命恩人。谢谢你,我的荣幸!:)谢谢…这看起来很有希望,查询结果与我试图实现的结果类似。现在,我将运行实际表的查询,并查看得到的结果。我得到一个错误:列名“EmployeeID”无效。我认为这是表描述中的一个输入错误。将查询中的
ed.EmployeeId
更改为
ed.[Employee ID]
。这样做了。工作得很有魅力。你是救命恩人。谢谢你,我的荣幸!:)