1

我正在使用 SQL Server。不知道是什么版本,但它仍然受支持。我有一个表,其中包含我感兴趣的 3 列。我需要更改“硬件”列中的列名以及每个列的计数。现在我有以下内容:

SELECT 
    COUNT(a.EAMacBook13) AS 'MacBook13', 
    COUNT(a.EAMacBook16) AS 'MacBook16', 
    COUNT(a.EAStandLaptop) AS 'StandLaptop' 
FROM 
    Employee AS e, EmpAttributes AS a 
WHERE 
    a.EAEmpID = e.EmpID AND e.EmpProjID = 1

在此处输入图像描述

相反,我需要类似的东西:

在此处输入图像描述

这可能吗?

4

3 回答 3

2

基本思想是反透视和计数。如果您的数据库支持横向连接(aka cross apply)并且values()您可以执行以下操作:

select x.hardware, count(x.val) cnt
from employee as e
inner join empattributes as ea on ea.eaempid = e.empid 
cross join lateral (values 
    ('EAMacBook13', ea.EAMacBook13), 
    ('EAMacBook16', ea.EAMacBook16), 
    ('EAStandLaptop', ea.EAStandLaptop)
) x(hardware, val)
where e.empprojid = 1
group by x.hardware

横向连接有不同的语法,具体取决于您的数据库。一些数据库使用cross apply而不是cross join lateral.

values()也不是到处都支持。例如,在 Oracle 中,您可以将横向连接表述为:

cross apply (
    select 'EAMacBook13' as hardware, EAMacBook13 as val from dual
    union all select 'EAMacBook16', EAMacBook16 from dual
    union all select 'EAStandLaptop', EAStandLaptop from dual
) x(hardware)

如果这些都不可用,那么我们可以回退union all

select x.hardware, count(x.val) cnt
from employee as e
inner join (
    select eaempid, 'EAMacBook13' as hardware, EAMacBook13 as value from empattributes 
    union all select eaempid, 'EAMacBook16', EAMacBook16 from empattributes 
    union all select eaempid, 'EAStandLaptop', EAStandLaptop from empattributes 
) x on x.eaempid = e.empid 
where e.empprojid = 1
group by x.hardware
于 2020-10-23T20:37:13.237 回答
2

你可以用一个简单的 union all 来做到这一点:

SELECT 'MacBook13' "Hardware", Count(a.EAMacBook13) "Count"
FROM Employee as e, EmpAttributes as a WHERE a.EAEmpID = e.EmpID and e.EmpProjID = 1
union all 
SELECT 'MacBook16' "Hardware", Count(a.EAMacBook16)  "Count"
FROM Employee as e, EmpAttributes as a WHERE a.EAEmpID = e.EmpID and e.EmpProjID = 1
union all 
SELECT 'StandLaptop' "Hardware", Count(a.EAStandLaptop)  "Count"
FROM Employee as e, EmpAttributes as a WHERE a.EAEmpID = e.EmpID and e.EmpProjID = 1

根据您的 RDBMS,您可能有权访问 UNPIVOT,这将减少编写工作。

您还可以使用 CTE 以便(如果您的 RDBMS 支持实现它们)您可以减少工作量:

with cte as (
  SELECT Count(a.EAMacBook13) as EAMacBook13, Count(a.EAMacBook16) as EAMacBook16, Count(a.EAStandLaptop) as EAStandLaptop
  FROM Employee as e, EmpAttributes as a WHERE a.EAEmpID = e.EmpID and e.EmpProjID = 1
)
SELECT 'MacBook13' "Hardware", EAMacBook13 "Count"
FROM  cte
union all 
SELECT 'MacBook16' "Hardware", MacBook16 "Count"
FROM cte
union all 
SELECT 'StandLaptop' "Hardware", StandLaptop "Count"
FROM cte

除非您使用某种程度的动态 SQL,否则您必须列出可能的硬件值。

于 2020-10-23T20:40:04.493 回答
0

一种选择是使用 Dynamic Unpivot。首先使用当前查询创建一个表:

SELECT a.EAMacBook13, a.EAMacBook16, a.EAStandLaptop
  INTO tab
  FROM Employee AS e 
  JOIN EmpAttributes AS a 
    ON a.EAEmpID = e.EmpID
 WHERE e.EmpProjID = 1

然后使用information_schema.columns

DECLARE @cols  AS NVARCHAR(MAX),  @query AS NVARCHAR(MAX)

SET  @query = 
    (SELECT STRING_AGG(CONCAT('SELECT ''',SUBSTRING(column_name,3,LEN(column_name)),''' AS Hardware, 
            COUNT(',column_name,') AS Count FROM tab '),' UNION ALL ')
       FROM information_schema.columns
      WHERE table_name = 'tab');

EXEC sp_executesql @query;

Demo

于 2020-10-23T21:53:08.563 回答