加入桌子和Union All / Pivot / Unpivot?

时间:2016-09-29 05:51:59

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

我在数据库中有四个表:

表1: Employee_Details

-----------------------------------------------------------------------
| Employee ID | Name  | Department |DateofJoining |
-----------------------------------------------------------------------
|             |       |            |              |
| e1          | name1 | d1         | date1        |
| e2          | name2 | d2         | date2        |
| e3          | name3 | d3         | date3        |
-----------------------------------------------------------------------

表2: Employee_SkillSet

----------------------------------------------------------------------------
| 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_Certifications

-----------------------------------------------------------------------
| EmployeeID | CertificationID |  Name  |
-----------------------------------------------------------------------
|            |                 |        |
| e1         | c1              | cname1 |
| e1         | c2              | cname2 |
| e2         | c3              | cname3 |
-----------------------------------------------------------------------

表4: Other_Details

----------------------------------------------------------------------------
| 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')

创建脚本:

3 个答案:

答案 0 :(得分:0)

您可以使用以下功能代替使用动态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

答案 1 :(得分:0)

Select TBl1.[EmployeeID],Tbl1.Name,Tbl1.Department,TBl1.Qualification, TBl1.TotalExp ,TBl1.Specialization,TBl1.[Certifications]
,Skill1_Exp,Skill1_Rating
,Skill2_Exp,Skill2_Rating
,Skill3_Exp,Skill3_Rating
From
(
    Select TBl1.[EmployeeID],Tbl1.Name,Tbl1.Department,Tbl4.Qualification, Tbl4.TotalExp ,Tbl4.Specialization,Tbl3.[Certifications]
    From Employee_Details Tbl1 Inner Join Employee_SkillSet Tbl2
    On TBl1.[EmployeeID]=TBl2.[EmployeeID]
    Inner Join 
    (
        SELECT Dtl.[EmployeeID],
                    STUFF((    SELECT ',' + Cer.CertificationID AS [text()]
                                FROM Employee_Certifications Cer
                                WHERE
                                Cer.[EmployeeID] = Dtl.[EmployeeID]
                                FOR XML PATH('')
                                ), 1, 1, '' )
                    AS [Certifications]
        FROM  Employee_Details Dtl
    ) as Tbl3
    On Tbl1.[EmployeeID]=Tbl3.[EmployeeID]
    Inner Join Other_Details as Tbl4
    On Tbl1.[EmployeeID]=Tbl4.[EmployeeID] 
    Group by TBl1.[EmployeeID],Tbl1.Name,Tbl1.Department,Tbl4.Qualification, Tbl4.TotalExp ,Tbl4.Specialization,Tbl3.[Certifications]
)as Tbl1
Inner Join
(
    Select Tbl1.[EmployeeID],Tbl1.skill1 as Skill1_Exp,Tbl2.skill1 as Skill1_Rating
    ,Tbl1.skill2 as Skill2_Exp,Tbl2.skill2 as Skill2_Rating
    ,Tbl1.skill3 as Skill3_Exp,Tbl2.skill3 as Skill3_Rating
    From
    (
        Select *
        from (seLECT [employeeID],SKILLNAME,SkillExperience FROM Employee_SkillSet )P
        PIVOT
        (max(SkillExperience )
            FOR SkillName IN([skill1], [skill2],[skill3])
        ) AS PivotSales 
    )as Tbl1
    Inner Join
    (
        Select *
        from (seLECT [employeeID],SKILLNAME,SKILLRATING FROM Employee_SkillSet )P
        PIVOT
        (
            max(SkillRating) 
            FOR SkillName IN([skill1], [skill2],[skill3])
        ) AS PivotSales
    )as Tbl2
    On Tbl1.[EmployeeID]=Tbl2.[EmployeeID]
) as Tbl2
On Tbl1.[EmployeeID]=Tbl2.[EmployeeID]

答案 2 :(得分:0)

您可以使用:

  • FOR XML PATH('')获取逗号分隔值
  • 动态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来传递逗号分隔值。< / p>