加入Vertical&使用Pivot的SQL Server中的水平表

时间:2016-12-21 07:21:42

标签: sql sql-server sql-server-2008

我想连接两个表并合并为一个但问题是一个表是水平格式而另一个是垂直格式。

下面是表结构,连接将在Employeeid上:

表1:EmpDetail

ID | CODE   | Name
-- |--------| ---
1  | 1008M  | ABC
2  | 1039E  | XYZ
3  | 1040E  | TYS

表2:EmpCustomeDetail

EmpID | FiledName   | FieldValue 
--    |--------     |  ---
1     | FlD1        | temp1
1     | FlD2        | temp2
1     | FlD3        | temp3
2     | FlD1        | temp1
3     | FLD4        | temp6

所需的输出要求:

EmpID |  Code |  Name | Fld1  | Fld2  | Fld3  | Fld4 
--    |----   | ------|  ---  | ----  |----   |----  
1     | 1008M | ABC   | temp1 | temp2 | temp3 | null
2     | 1039E | XYZ   | temp1 | null  | null  | null
3     | 1040E | TYS   | null  | null  | null  | temp6

我曾尝试使用Pivot Query,但它没有提供我需要的确切输出 以下是我尝试过的查询

SELECT A.*
FROM (
    SELECT
        e.Id,
        e.code,
        e.Fname,        
    FROM EmpDetail e  
    LEFT JOIN (
        SELECT *
        FROM (
            SELECT
                  d.CustomeFieldName
                , c.ComboValue
                , d.EmployeeId              
            FROM EmpCustomeDetail d
        ) src 
        PIVOT (
            MAX(FieldValue)          
        ) src2
    ) c ON e.Id = c.EmployeeId       

) A

3 个答案:

答案 0 :(得分:3)

以下是两个陈述:

第一个是简单的PIVOT。您可以使用它,以防您事先了解所有Fieldnames(顺便说一下:样本中有错字)。

第二个是大致相同的语句,但列名是动态获取的。这将(几乎)任何计数和不同的命名。

首先是模拟 -test-scenraio

CREATE TABLE DummyEmpDetail (ID INT,CODE VARCHAR(10),Name VARCHAR(100));
INSERT INTO DummyEmpDetail VALUES
 (1,'1008M','ABC')
,(2,'1039E','XYZ')
,(3,'1040E','TYS');

CREATE TABLE DummyEmpCustomeDetail (EmpID INT,FiledName VARCHAR(100),FieldValue VARCHAR(100)); 
INSERT INTO DummyEmpCustomeDetail VALUES
 (1,'FlD1','temp1')
,(1,'FlD2','temp2')
,(1,'FlD3','temp3')
,(2,'FlD1','temp1')
,(3,'FLD4','temp6');

- 静态PIVOT语句

SELECT p.EmpID
      ,p.Name
      ,p.CODE
      ,p.Fld1
      ,p.Fld2
      ,p.Fld3
      p,Fld4
FROM
(
    SELECT e.CODE,e.Name,ec.*
    FROM DummyEmpDetail AS e
    INNER JOIN DummyEmpCustomeDetail AS ec ON e.ID=ec.EmpID
) AS tbl
PIVOT
(
    MAX(FieldValue) FOR FiledName IN(Fld1,Fld2,Fld3,Fld4)
) AS p;

- 动态PIVOT语句

DECLARE @colNames VARCHAR(MAX)=
(
    STUFF
    (
        (
            SELECT DISTINCT ',' + QUOTENAME(FiledName) FROM DummyEmpCustomeDetail
            FOR XML PATH('')
        ),1,1,''
    )   
);
DECLARE @command VARCHAR(MAX)=
'SELECT p.EmpID
      ,p.Name
      ,p.CODE
      ,' + @colNames + 
' FROM
(
    SELECT e.CODE,e.Name,ec.*
    FROM DummyEmpDetail AS e
    INNER JOIN DummyEmpCustomeDetail AS ec ON e.ID=ec.EmpID
) AS tbl
PIVOT
(
    MAX(FieldValue) FOR FiledName IN(' + @colnames + ')
) AS p;';

EXEC (@command);
GO

DROP TABLE DummyEmpCustomeDetail;
DROP TABLE DummyEmpDetail;

两者都导致相同的结果......

答案 1 :(得分:1)

尝试如下。如果fieldname的值不是静态的,那么您应该使用dynamic sql

 SELECT EMPID,
           CODE,
           NAME,
           FLD1,
           FLD2,
           FLD3,
           FLD4
    FROM   EmpDetail C
           JOIN (SELECT A.*
                 FROM   EmpCustomeDetail
                        PIVOT ( MIN([FIELDVALUE])
                              FOR [FILEDNAME] IN([FLD1],
                                                 [FLD3],
                                                 [FLD2],
                                                 FLD4) )A)B
             ON C.ID = B.[EMPID] 

答案 2 :(得分:1)

无需子查询。

select  e.*,FlD1,FlD2,FlD3,FlD4 
from    EmpDetail e
        left join EmpCustomeDetail 
                      pivot (max(FieldValue) for FiledName in (FlD1,FlD2,FlD3,FlD4)) ecd
        on ecd.EmpID = e.ID
+----+-------+------+-------+-------+-------+-------+
| ID | CODE  | Name | FlD1  | FlD2  | FlD3  | FlD4  |
+----+-------+------+-------+-------+-------+-------+
| 1  | 1008M | ABC  | temp1 | temp2 | temp3 | NULL  |
+----+-------+------+-------+-------+-------+-------+
| 2  | 1039E | XYZ  | temp1 | NULL  | NULL  | NULL  |
+----+-------+------+-------+-------+-------+-------+
| 3  | 1040E | TYS  | NULL  | NULL  | NULL  | temp6 |
+----+-------+------+-------+-------+-------+-------+