删除Oracle中的额外子查询,选择值数组

时间:2009-09-25 18:13:00

标签: sql oracle optimization plsql

我正在选择一些汇总数据并对日期和特定字段进行分组。我希望显示该字段中的所有值以及这些值的计数,即使当天没有与该字段匹配的数据。 E.g。

Date        MyField  Count
2009-09-25  A        2
2009-09-25  B        0
2009-09-24  A        1
2009-09-24  B        1

我目前必须执行此操作的Oracle SQL类似于以下内容:

SELECT today,
       mytable.myfield,
       COUNT(
         CASE WHEN fields.myfield = mytable.myfield AND
                   date >= today AND
                   date < tomorrow
              THEN 1
         END
       )
FROM (
       SELECT TRUNC(SYSDATE) + 1 - LEVEL AS today,
              TRUNC(SYSDATE) + 2 - LEVEL AS tomorrow
       FROM DUAL
       CONNECT BY LEVEL <= 30
     ),
     (
       /* This is the part that seems inefficient */
       SELECT DISTINCT myfield
       FROM mytable
       WHERE myfield IN ('A', 'B')
     ) fields,
     mytable
GROUP BY today, mytable.myfield
ORDER BY today DESC, mytable.myfield ASC

我担心的是,我确切地知道要为myfield显示哪些值,并且使用SELECT查询来访问mytable似乎效率低下。我想知道是否有一些方法可以在子查询中做这样的事情:

SELECT ('A', 'B') AS myfield
FROM DUAL

我正在使用旧版本的Oracle,其中WITH子句不起作用。

3 个答案:

答案 0 :(得分:1)

您必须将它们作为不同的行,而不是不同的列。所以你最终会得到

select 'A' from dual
union
select 'B' from dual

在这种情况下,只要mytable中的行包含字段“A”和“B”,查询就应该是等效的。如果没有,则子查询将返回原始子查询不会返回的行。

答案 1 :(得分:0)

为什么不升级Oracle版本? with子句首先添加到Oracle 9.2(2002)。你还在使用Oracle 8吗?

答案 2 :(得分:0)

您在FIELDS子查询和MYTABLE之间没有连接,因此您的结果集将包含过去30天内 MYFIELD的每个值的行。

但是,为什么不放弃子查询而只是过滤MYTABLE.MYFIELD,而不是添加该连接?此外,如果您担心性能,则应将日期绑定在WHERE子句中,否则您将处理MYTABLE中的每一行。

select today
       , myfield
       , count ( case when trunc(somedate) = today then 1 end ) as ab_count
from   ( select trunc(sysdate) + 1 - level as today
         from dual
         connect by level <= 30 )
       , mytable
where myfield in ('A', 'B')
and somedate >= trunc(sysdate) - 30
group by today, myfield
order by today desc, myfield asc
/

修改

我已经针对某些测试数据运行了您的原始查询和我修改过的查询。您将不得不接受我的说法,即两个结果实际上是相同的 - 或者自己尝试一下:)

您的查询返回:

TODAY       M   AB_COUNT
----------- - ----------
26-SEP-2009 A          0
26-SEP-2009 B          0
25-SEP-2009 A          2
25-SEP-2009 B          2
24-SEP-2009 A          2
24-SEP-2009 B          0
...
29-AUG-2009 A          1
29-AUG-2009 B          2
28-AUG-2009 A          1
28-AUG-2009 B          0

60 rows selected.

SQL>

我的查询返回:

TODAY       M   AB_COUNT
----------- - ----------
26-SEP-2009 A          0
26-SEP-2009 B          0
25-SEP-2009 A          2
25-SEP-2009 B          2
24-SEP-2009 A          2
24-SEP-2009 B          0
...
29-AUG-2009 A          1
29-AUG-2009 B          2
28-AUG-2009 A          1
28-AUG-2009 B          0

60 rows selected.

SQL>