使用不同的WHERE子句重构类似的子查询

时间:2013-08-21 19:03:50

标签: sql oracle

我继承了一个迫切需要重构的SQL查询。查询(6页长)看起来像这样:

SELECT (count(*) from tab1, tab2, tab3 where tab1.value1 is not null 
and tab2.tab3id = tab3.id and tab3.value4 in (1,2,3) and tab3.value3 = 15 and tab2.value2 = 10 [...]) as RESULT1,
SELECT (sum(tab3.value5) from [EXACT SAME QUERY AS ABOVE]) AS RESULT1_SUM
SELECT (count(*) from tab1, tab2, tab3 where tab1.value1 is not null
and tab2.tab3id = tab3.id and tab3.value4 in (1,2,3) and tab3.value3 = 15 and tab2.value2 = 27 [...]) as RESULT2,
...[AD NAUSEAM for several more columns]
UNION
SELECT [same as first query, but now tab1.value1 is NULL]
...[now sum()]
FROM DUAL [of course!]

这个混乱的最终结果是一个2行/ 16列结果,其中行的不同是tab1.value1在(主要是复制和粘贴)子查询中是否为空,并且列的不同之处在于子查询的WHERE子句的其他值。

             RESULT1  RESULT1_SUM  RESULT2  RESULT2_SUM ...
IS_NOT_NULL       300       120000     90         80000
IS_NULL            70        90000     54         95000

我必须复制同样的输出。我的第一直觉是将子查询的公共元素拉出到WITH子句中。但我仍然坚持如何在不使用每列的单独子查询的情况下获得“WHERE子句的小变化 - >不同命名列”元素的复制。

我应该把它搞砸并将子查询转储到全局临时表中还是有更好的方法?

1 个答案:

答案 0 :(得分:1)

如果列之间的主要差异为tab2.value2,那么您可以编写一个包含两个阶段的查询:

  1. 内部查询,用于选择相关数据并按tab2.value2分组

  2. 将结果分配给列的外部查询

  3. 因此,对于查询的前半部分,它可能如下所示:

    select
      sum(case when val = 10 then cnt end) as RESULT1,
      sum(case when val = 10 then sm  end) as RESULT1_SUM,
      sum(case when val = 15 then cnt end) as RESULT2,
      sum(case when val = 15 then sm  end) as RESULT2_SUM,
      ...
    from (
      select tab2.value2 as val, count(*) as cnt, sum(tab3.value5) as sm
      from tab1, tab2, tab3
      where tab1.value1 is not null 
        and tab2.tab3id = tab3.id
        and tab3.value4 in (1,2,3)
        and tab3.value3 = 15
      group by tab2.value2
    )