繁体   English   中英

如何将两个查询(union all)合并为一行?

[英]How do I combine two queries (union all) into one row?

在尝试将多个查询中的信息转换为单行时,我遇到了一个棘手的情况。

请考虑下表:

CpuUage:
    Time    time
    Group   char(10)
    Subsys  char(4)
    Jobs    int
    Cpu     int

持有以下数据:

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) --

右侧的标记(例如, A1 )是下面报告中每行应该影响的部分。

我需要一个查询,可以为每个用户组返回一行,但有一个附带条件。 JobsCpu的值必须根据子系统ID进入不同的列,我只对SYS7NORM子系统ID感兴趣。

因此,例如,我们需要以下内容( 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

我们的旧报告解决方案可以运行多个查询(使用union all ),然后对行进行后处理以组合具有相同组名的行,以便:

Group   NormJobs  NormCpu  Sys7Jobs  Sys7Cpu
------  --------  -------  --------  -------
group1        13      313         0        0
group1         0        0        16      266

按照以下方式合并在一起:

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

不幸的是,我们的新解决方案不允许进行后处理,所有这些都必须在SQL查询中完成。

请记住,可能存在具有SYS7行, NORM行,两者或两者的组,实现此目的的最佳方法是什么?

我想过从外部选择中查询表格,但可能会产生性能影响。

此外,这将是一个痛苦,因为我必须使外部查询包括NORM和SYS7子系统,然后为每个字段运行子查询(我不能只为NORM作业的外部查询,因为存在一个组只有SYS7行才会被捕获。)

您是否可以编织任何左中间内侧越位魔法来提出可行的解决方案?

我更喜欢与供应商无关的解决方案,但是,如果您必须特定于供应商,则该平台是DB2。 不过,其他平台至少可以给我一些尝试的想法,所以我很高兴看到它们。

我不明白子查询的问题,看起来它应该同样快:

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

这是一个数据透视表查询。 (如果您需要更多信息,请搜索。)

您想要的查询结构类似于以下内容:

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

这是一个典型的数据透视查询 - 以下是使用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

不幸的是,当Oracle / SQL Server / MySQL / Postgres没有时,DB2的CASE语句需要以END CASE结束。 那么,PLSQL支持END CASE ......

还有PIVOT语法 ,Oracle 11g和SQL Server 2005+也支持该语法

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM