Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将列名更改为单列值的SQL查询_Sql_Sql Server_Count_Unpivot_Lateral Join - Fatal编程技术网

将列名更改为单列值的SQL查询

将列名更改为单列值的SQL查询,sql,sql-server,count,unpivot,lateral-join,Sql,Sql Server,Count,Unpivot,Lateral Join,我正在使用SQL Server。不确定是哪个版本,但它仍然受支持。 我有一个表,其中有3列是我感兴趣的。我需要更改“硬件”列中的列名以及每个列的计数。现在我有以下几点: SELECT COUNT(a.EAMacBook13) AS 'MacBook13', COUNT(a.EAMacBook16) AS 'MacBook16', COUNT(a.EAStandLaptop) AS 'StandLaptop' FROM Employee AS e, Emp

我正在使用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

相反,我需要的是:


这是可能的吗?

基本思想是解算和计数。如果您的数据库支持横向联接(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
根据您的数据库,有不同的语法可用于横向联接。一些数据库使用
交叉应用
而不是
交叉连接横向

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

其基本思想是解算和计数。如果您的数据库支持横向联接(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
根据您的数据库,有不同的语法可用于横向联接。一些数据库使用
交叉应用
而不是
交叉连接横向

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

您可以通过一个简单的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,否则您必须列出可能的硬件值。

您可以通过简单的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,否则必须列出可能的硬件值。

一个选项是使用动态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
然后使用
信息\u模式。列

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;

一个选项是使用动态取消PIVOT。首先使用当前查询创建一个表:

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
然后使用
信息\u模式。列

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;

请用您正在运行的数据库标记您的问题:mysql、oracle、postgresql…?-在ANSI-92 SQL标准(超过25年前)中,旧样式的逗号分隔表列表样式已被正确的ANSI
JOIN
语法所取代,不鼓励使用它通过在SSMS中运行
SELECT@@version
来查找SQL Server的版本请使用您正在运行的数据库标记您的问题:mysql,oracle,postgresql…?-在ANSI-92 SQL标准中(超过25年前),用正确的ANSI
JOIN
语法替换了老式的逗号分隔表列表样式不鼓励使用它通过在SSMs中运行
SELECT@@version
查找SQL Server的版本第三个值缺少一个union all,但这正是我所需要的。谢谢。你错过了第三个值的联合,但这正是我所需要的。谢谢。@JimBedson:我看到你现在在SQL Server上标记了你的问题。在此数据库中,您可以使用第一个查询-只需将
交叉连接横向
替换为
交叉应用
。这比您接受的答案中的
union all
更有效,因为它只扫描表一次。@JimBedson:我看到您现在将问题标记为SQL Server。在此数据库中,您可以使用第一个查询-只需将
交叉连接横向
替换为
交叉应用
。这比您接受的答案中的
union all
更有效,因为它只扫描表一次。