SQL Server 2008 R2:VARCHAR列上的透视表

SQL Server 2008 R2:VARCHAR列上的透视表,sql,sql-server-2008-r2,pivot-table,Sql,Sql Server 2008 R2,Pivot Table,表格: CREATE TABLE EMPDetails ( ID int, EmpName varchar(20), ColumnName varchar(20), ColumnValue varchar(20) ); INSERT INTO EMPDetails Values(1,'S','Company','Microsoft'); INSERT INTO EMPDetails Values(1,'S','Profession','Database'); I

表格

CREATE TABLE EMPDetails
(
    ID int,
    EmpName varchar(20),
    ColumnName varchar(20),
    ColumnValue varchar(20)
);
INSERT INTO EMPDetails Values(1,'S','Company','Microsoft');
INSERT INTO EMPDetails Values(1,'S','Profession','Database');
INSERT INTO EMPDetails Values(1,'S','Location','USA');
INSERT INTO EMPDetails Values(1,'S','Company','Unisys');
INSERT INTO EMPDetails Values(1,'S','Company','TATA');

INSERT INTO EMPDetails Values(2,'U','Company','Microsoft');
INSERT INTO EMPDetails Values(2,'U','Profession','Software');
INSERT INTO EMPDetails Values(2,'U','Location','UK');
INSERT INTO EMPDetails Values(2,'U','Company','DXC');
INSERT INTO EMPDetails Values(2,'U','Company','AOL');

INSERT INTO EMPDetails Values(3,'R','Company','Microsoft');
INSERT INTO EMPDetails Values(3,'R','Profession','Software');
INSERT INTO EMPDetails Values(3,'R','Location','UK');
INSERT INTO EMPDetails Values(3,'R','Company','AOL');
记录

CREATE TABLE EMPDetails
(
    ID int,
    EmpName varchar(20),
    ColumnName varchar(20),
    ColumnValue varchar(20)
);
INSERT INTO EMPDetails Values(1,'S','Company','Microsoft');
INSERT INTO EMPDetails Values(1,'S','Profession','Database');
INSERT INTO EMPDetails Values(1,'S','Location','USA');
INSERT INTO EMPDetails Values(1,'S','Company','Unisys');
INSERT INTO EMPDetails Values(1,'S','Company','TATA');

INSERT INTO EMPDetails Values(2,'U','Company','Microsoft');
INSERT INTO EMPDetails Values(2,'U','Profession','Software');
INSERT INTO EMPDetails Values(2,'U','Location','UK');
INSERT INTO EMPDetails Values(2,'U','Company','DXC');
INSERT INTO EMPDetails Values(2,'U','Company','AOL');

INSERT INTO EMPDetails Values(3,'R','Company','Microsoft');
INSERT INTO EMPDetails Values(3,'R','Profession','Software');
INSERT INTO EMPDetails Values(3,'R','Location','UK');
INSERT INTO EMPDetails Values(3,'R','Company','AOL');
我的尝试

条件1
Company='Microsoft'和Profession='Database'

预期结果:

ID  EmpName Company     Profession  Location
-----------------------------------------
1   S       Microsoft   Database    USA
查询:

SELECT *
FROM 
(
  SELECT ID, EmpName,ColumnValue, ColumnName
  FROM EMPDetails
) src
PIVOT
(
  MAX(ColumnValue) /*OR MIN()*/
  FOR ColumnName in ([Company], [Profession], [Location])
) piv
WHERE Company = 'Microsoft' AND Profession = 'Database'  
条件2
公司='Microsoft'和专业='Software'

预期结果:

ID  EmpName Company     Profession  Location
-----------------------------------------
3   R       Microsoft   Software    UK
2   U       Microsoft   Software    UK
查询:

SELECT *
FROM 
(
  SELECT ID, EmpName,ColumnValue, ColumnName
  FROM EMPDetails
) src
PIVOT
(
  MAX(ColumnValue) /*OR MIN()*/
  FOR ColumnName in ([Company], [Profession], [Location])
) piv
WHERE Company = 'Microsoft' AND Profession = 'Software'

问题:如果我在条件1中使用
MIN()
聚合函数,那么将得到结果,但在
MAX()
中不会,条件2则相反。为什么?

您可以
按员工分组,并在
HAVING
子句中使用条件计数,以获得满足条件的员工:

SELECT ID, EmpName      
FROM EMPDetails 
GROUP BY ID, EmpName
HAVING COUNT(CASE 
                WHEN ColumnName = 'Company' AND 
                     ColumnValue = 'Microsoft' THEN 1 
             END) > 0
       AND 
       COUNT(CASE 
                WHEN ColumnName = 'Profession' AND 
                ColumnValue = 'Database' THEN 1 
             END) > 0
上述查询选择拥有
Microsoft
作为
公司的员工,以及拥有
数据库的员工作为
职业的员工

输出:

ID  EmpName
------------
1   S
ID  EmpName Company     Profession  Location
-----------------------------------------
1   S       Microsoft   Database    USA
ID  EmpName Company     Profession  Location
---------------------------------------------
3   R       Microsoft   Software    UK
2   U       Microsoft   Software    UK
现在可以使用条件聚合来透视员工行:

SELECT ID, EmpName,
       'Microsoft' AS Company,
       'Database' AS Profession,
       MAX(CASE WHEN ColumnName = 'Location' THEN ColumnValue END) AS Location
FROM EMPDetails 
GROUP BY ID, EmpName
HAVING COUNT(CASE 
                WHEN ColumnName = 'Company' AND 
                     ColumnValue = 'Microsoft' THEN 1 
             END) > 0
       AND 
       COUNT(CASE 
                WHEN ColumnName = 'Profession' AND 
                     ColumnValue = 'Database' THEN 1 
             END) > 0
无需对公司或专业价值进行汇总,因为所需价值保证属于员工群体

输出:

ID  EmpName
------------
1   S
ID  EmpName Company     Profession  Location
-----------------------------------------
1   S       Microsoft   Database    USA
ID  EmpName Company     Profession  Location
---------------------------------------------
3   R       Microsoft   Software    UK
2   U       Microsoft   Software    UK
要获得第二个结果集,只需将
数据库
替换为
软件

SELECT ID, EmpName,
       'Microsoft' AS Company,
       'Software' AS Profession,
       MAX(CASE WHEN ColumnName = 'Location' THEN ColumnValue END) AS Location
FROM EMPDetails 
GROUP BY ID, EmpName
HAVING COUNT(CASE 
                WHEN ColumnName = 'Company' AND 
                     ColumnValue = 'Microsoft' THEN 1 
             END) > 0
       AND 
       COUNT(CASE 
                WHEN ColumnName = 'Profession' AND 
                     ColumnValue = 'Software' THEN 1 
             END) > 0
输出:

ID  EmpName
------------
1   S
ID  EmpName Company     Profession  Location
-----------------------------------------
1   S       Microsoft   Database    USA
ID  EmpName Company     Profession  Location
---------------------------------------------
3   R       Microsoft   Software    UK
2   U       Microsoft   Software    UK

这两个案例的预期结果是什么?@GiorgosBetsos,用预期结果编辑。您对#2的条件实际上是有效的:您是否总是返回相同的列(
id
EmpName
公司
职业
位置
)?你会永远只在那些栏上搜索吗?或者您可能希望搜索其他
ColumnName
值,但不一定要将它们包含在结果中?如果您只搜索了
Profession='database'
,那么应该为员工1返回什么信息,因为他们有3个关联公司(3行,每个公司一个)?@JohnWoo,请阅读问题(已编辑)。