将列名更改为单列值的SQL查询
我正在使用SQL Server。不确定是哪个版本,但它仍然受支持。 我有一个表,其中有3列是我感兴趣的。我需要更改“硬件”列中的列名以及每个列的计数。现在我有以下几点:将列名更改为单列值的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
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年前)中,旧样式的逗号分隔表列表样式已被正确的ANSIJOIN
语法所取代,不鼓励使用它通过在SSMS中运行SELECT@@version
来查找SQL Server的版本请使用您正在运行的数据库标记您的问题:mysql,oracle,postgresql…?-在ANSI-92 SQL标准中(超过25年前),用正确的ANSIJOIN
语法替换了老式的逗号分隔表列表样式不鼓励使用它通过在SSMs中运行SELECT@@version
查找SQL Server的版本第三个值缺少一个union all,但这正是我所需要的。谢谢。你错过了第三个值的联合,但这正是我所需要的。谢谢。@JimBedson:我看到你现在在SQL Server上标记了你的问题。在此数据库中,您可以使用第一个查询-只需将交叉连接横向
替换为交叉应用
。这比您接受的答案中的union all
更有效,因为它只扫描表一次。@JimBedson:我看到您现在将问题标记为SQL Server。在此数据库中,您可以使用第一个查询-只需将交叉连接横向
替换为交叉应用
。这比您接受的答案中的union all
更有效,因为它只扫描表一次。