[英]How do I combine two queries (union all) into one row?
I have a tricky situation in trying to get information from multiple queries into a single row. 在尝试将多个查询中的信息转换为单行时,我遇到了一个棘手的情况。
Consider the following table: 请考虑下表:
CpuUage:
Time time
Group char(10)
Subsys char(4)
Jobs int
Cpu int
holding the following data: 持有以下数据:
Time Group Subsys Jobs Cpu
----- ------ ------ ---- ---
00:00 group1 NORM 1 101 (grp1-norm) A1
01:00 group1 SYS7 3 102 (grp1-sys7) A2
01:00 group1 NORM 5 104 (grp1-norm) A1
02:00 group1 NORM 7 108 (grp1-norm) A1
02:00 group2 NORM 9 116 (grp2-norm) B1
02:00 group3 SYS7 11 132 (grp3-sys7) C2
03:00 group1 SYS7 13 164 (grp1-sys7) A2
03:00 group1 IGNR 99 228 (grp1-ignr) --
The markers on the right (eg, A1
) are the sections in the report below that each row is supposed to affect. 右侧的标记(例如,
A1
)是下面报告中每行应该影响的部分。
I need a query that can return a single row for each user group but with one proviso. 我需要一个查询,可以为每个用户组返回一行,但有一个附带条件。 The values for
Jobs
and Cpu
have to go into different columns depending on the subsystem ID and I'm only interested in the SYS7
and NORM
subsystem IDs. Jobs
和Cpu
的值必须根据子系统ID进入不同的列,我只对SYS7
和NORM
子系统ID感兴趣。
So, for example, we need the following (the A/B/1/2
bits are a cross-reference back to the rows above): 因此,例如,我们需要以下内容(
A/B/1/2
位是交叉引用,返回上面的行):
<------ 1 ------> <------ 2 ------>
Group NormJobs NormCpu Sys7Jobs Sys7Cpu
------ -------- ------- -------- -------
A: group1 13 313 16 266
B: group2 9 116 0 0
C: group3 0 0 11 164
Our old reporting solution could run multiple queries (with a union all
), then post-process the rows to combine those with the same group name, so that: 我们的旧报告解决方案可以运行多个查询(使用
union all
),然后对行进行后处理以组合具有相同组名的行,以便:
Group NormJobs NormCpu Sys7Jobs Sys7Cpu
------ -------- ------- -------- -------
group1 13 313 0 0
group1 0 0 16 266
were merged together, along the lines of: 按照以下方式合并在一起:
select groupname, sum(jobs), sum(cpu), 0, 0 from tbl
where subsys = 'NORM'
group by groupname
union all
select groupname, 0, 0, sum(jobs), sum(cpu) from tbl
where subsys = 'SYS7'
group by groupname
Unfortunately, our new solution does not allow post-processing and it all has to be done in the SQL query. 不幸的是,我们的新解决方案不允许进行后处理,所有这些都必须在SQL查询中完成。
Keeping in mind that there may be groups with SYS7
rows, NORM
rows, both or neither, what's the best way to achieve this? 请记住,可能存在具有
SYS7
行, NORM
行,两者或两者的组,实现此目的的最佳方法是什么?
I thought about sub-querying the table from within an outer select but that may have performance ramifications. 我想过从外部选择中查询表格,但可能会产生性能影响。
In addition, that would be a pain since I'd have to make the outer query include NORM and SYS7 subsystems then run a subquery for every field (I can't make the outer query just for NORM
jobs since the presence of a group with only SYS7
rows wouldn't be caught that way). 此外,这将是一个痛苦,因为我必须使外部查询包括NORM和SYS7子系统,然后为每个字段运行子查询(我不能只为
NORM
作业的外部查询,因为存在一个组只有SYS7
行才会被捕获。)
Can you bods weave any of your left-middle-inner-offside-join magic to come up with a viable solution? 您是否可以编织任何左中间内侧越位魔法来提出可行的解决方案?
I'd prefer a vendor-agnostic solution but, if you must go vendor-specific, the platform is DB2. 我更喜欢与供应商无关的解决方案,但是,如果您必须特定于供应商,则该平台是DB2。 Still, other platforms may at least give me an ideas of what to try so I'm happy to see them.
不过,其他平台至少可以给我一些尝试的想法,所以我很高兴看到它们。
I don't understand the problem with sub-querying, it seems like it should be just as fast: 我不明白子查询的问题,看起来它应该同样快:
select
sub.gn as groupname,
sum(sub.nj) as NormJobs, sum(sun.nc) as NormCpu,
sum(sub.sj) as Sys7Jobs, sum(sub.sc) as Sys7Cpu
from (
select
groupname as gn,
sum(jobs) as nj, sum(cpu) as nc,
0 as sj, 0 as sc
from tbl
where subsys = 'NORM'
group by groupname
union all select
groupname as gn,
0 as nj, 0 as nc,
sum(jobs) as sj, sum(cpu) as sc
from tbl
where subsys = 'SYS7'
group by groupname
) as sub
group by sub.gn
order by 1
This is a pivot table query. 这是一个数据透视表查询。 (Search on that if you require further info.)
(如果您需要更多信息,请搜索。)
The query structure you want is something along the lines of the following: 您想要的查询结构类似于以下内容:
SELECT groupname,
SUM(CASE WHEN subsys = 'NORM' THEN jobs ELSE 0 END) AS NormJobs,
SUM(CASE WHEN subsys = 'NORM' THEN cpu ELSE 0 END) AS NormCpu,
SUM(CASE WHEN subsys = 'SYS7' THEN jobs ELSE 0 END) AS Sys7Jobs,
SUM(CASE WHEN subsys = 'SYS7' THEN cpu ELSE 0 END) AS Sys7Cpu,
SUM(CASE WHEN subsys NOT IN ('NORM', 'SYS7') THEN jobs ELSE 0 END) AS OtherJobs,
SUM(CASE WHEN subsys NOT IN ('NORM', 'SYS7') THEN cpu ELSE 0 END) AS OtherCpu
FROM ???
GROUP BY groupname
It's a typical pivot query - here's how you'd do it with CASE statements : 这是一个典型的数据透视查询 - 以下是使用CASE语句执行此操作的方法:
SELECT t.group,
SUM(CASE
WHEN t.subsys = 'NORM' THEN t.jobs
ELSE NULL
END CASE) AS NormJobs,
SUM(CASE
WHEN t.subsys = 'NORM' THEN t.cpu
ELSE NULL
END CASE) AS NormCpu,
SUM(CASE
WHEN t.subsys = 'SYS7' THEN t.jobs
ELSE NULL
END CASE) AS Sys7Jobs,
SUM(CASE
WHEN t.subsys = 'SYS7' THEN t.cpu
ELSE NULL
END CASE) AS Sys7Cpu
FROM CPUUSAGE t
GROUP BY t.group
Unfortunately, DB2's CASE statements need to end with END CASE
, when Oracle/SQL Server/MySQL/Postgres doesn't. 不幸的是,当Oracle / SQL Server / MySQL / Postgres没有时,DB2的CASE语句需要以
END CASE
结束。 Well, PLSQL supports END CASE
... 那么,PLSQL支持
END CASE
......
There's also the PIVOT syntax , which is also supported on Oracle 11g, and SQL Server 2005+. 还有PIVOT语法 ,Oracle 11g和SQL Server 2005+也支持该语法 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.