我正在选择一些汇总数据并对日期和特定字段进行分组。我希望显示该字段中的所有值以及这些值的计数,即使当天没有与该字段匹配的数据。 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
子句不起作用。
答案 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>