2012-02-03 56 views
2

给定一个表是这样的:`PIVOT`用`EXISTS`

[Last Name] [First Name] [DepartmentID] 
--------------------------------------- 
Doe   John   1 
Doe   John   2 
Black  Frank  3 

,我想这样的结果:

[Last Name] [First Name] [Accounting] [Management] [Development] 
---------------------------------------------------------------- 
Doe   John   X   X 
Black  Frank         X 

到目前为止,我有这样的查询:

SELECT [Last Name], [First Name], [1], [2], [3] 
FROM Employees 
PIVOT(SUM(DepartmentID) FOR DepartmentID IN ([1], [2], [3]) 
GROUP BY [Last Name], [First Name], [1], [2], [3] 

这给了我:

[Last Name] [First Name] [1] [2] [3] 
---------------------------------------------------------------- 
Doe   John   1 
Doe   John    2 
Black  Frank    3 

几个问题:

  • 列名称来自别处,即应当从函数或子查询的。这可以做到吗?
  • 我假设我将不得不使用动态SQL来获取可能的部门,即我不能告诉PIVOT只是确定所有可能性?
  • 列值应该是'X'(或类似),不包含实际值。每个可能的部门不应该有多行,这意味着我无法通过枢轴列进行分组。我如何获得每人一行?

我真的不想要或不需要聚合任何东西;我只是希望根据每个部门展示该员工是否居住在该部门。是PIVOT这个红鲱鱼吗?我可以用更复杂的方式解决这个问题,每个部门有EXISTS声明?

+1

您应该删除'GROUP BY [姓氏],[名],[1] ,[2],[3]'位。这是毫无意义的。顺便说一句,你必须在你的表中有一个额外的列,你没有向我们显示像导致多行问题的“RecordId”。 [每位员工只返回1行](http://data.stackexchange.com/stackoverflow/query/60760/new) – 2012-02-03 17:57:06

+0

确实有更多的列,它们可能会有所不同。你也是正确的,PIVOT似乎意味着GROUP BY。 – 2012-02-03 18:21:43

+0

解决方法是使用CTE或派生表作为仅包含3列感兴趣的PIVOT源。你可以使用'CASE'语句来获得你的'X'而不是数字。如果列列表是动态的,则需要动态SQL。 – 2012-02-03 18:24:41

回答

9

也许这将帮助:

首先是一些测试数据:

CREATE TABLE tbl(LastName VARCHAR(100),FirstName VARCHAR(100),DepartmentID INT) 
CREATE TABLE tblDepartment(DepartmentID INT,Name VARCHAR(100)) 

INSERT INTO tbl 
SELECT 'Doe','John',1 UNION ALL 
SELECT 'Doe','John',2 UNION ALL 
SELECT 'Black','Frank',3 

INSERT INTO tblDepartment 
SELECT 1,'Accounting' UNION ALL 
SELECT 2,'Management' UNION ALL 
SELECT 3,'Development' 

的concating列:

DECLARE @cols VARCHAR(MAX) 
SELECT @cols = COALESCE(@cols + ','+QUOTENAME(Name), 
        QUOTENAME(Name)) 
FROM 
    tblDepartment 
ORDER BY 
    Name 

或者你可能想Concat的只用现有的列像这样:

DECLARE @cols VARCHAR(MAX) 
SELECT @cols = COALESCE(@cols + ','+QUOTENAME(Name), 
        QUOTENAME(Name)) 
FROM 
    tblDepartment 
WHERE EXISTS 
     (
      SELECT 
       NULL 
      FROM 
       tbl AS tbl2 
      WHERE 
       tblDepartment.DepartmentID=tbl2.DepartmentID) 
ORDER BY 
    Name 

然后执行动态SQL:

DECLARE @query NVARCHAR(4000)= 
N'SELECT 
    * 
FROM 
(
    SELECT 
     tbl.LastName, 
     tbl.FirstName, 
     Department.Name, 
     ''X'' as test 
    FROM 
     tbl AS tbl 
     JOIN tblDepartment AS Department 
      ON Department.DepartmentID=tbl.DepartmentID 
)AS p 
PIVOT 
(
    MAX(test) FOR Name IN ('[email protected]+') 
) As Pvt' 

EXECUTE(@query) 

而在我的情况下丢弃创建的表:

DROP TABLE tbl 
DROP TABLE tblDepartment 
+2

+1;你也可以用'QUOTENAME'(Name,'[')''替换''['+ Name +']''' – 2012-02-04 12:39:01

+0

不知道。这很干净。谢谢。更新anser。 – Arion 2012-02-04 13:16:25

+0

或者我可以使用QUOTENAME(Name),因为默认值是'[',第二个参数不是必需的。 – Arion 2012-02-04 13:22:40