简体   繁体   English

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

[英]removing extra sub-query in Oracle, selecting array of values

I'm SELECTing some aggregate data and grouping on the date and a particular field. 我正在选择一些汇总数据并按日期和特定字段分组。 I want to display all values in that field and a count for those values even if there was no data matching that field on that day. 我想显示该字段中的所有值以及这些值的计数,即使当天没有与该字段匹配的数据也是如此。 Eg 例如

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

The Oracle SQL I currently have to do this is akin to the following: 我目前必须执行的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

My concern is that I know exactly which values I want to display for myfield , and it seems inefficient to have a SELECT query that accesses mytable . 我担心的是,我确切知道要为myfield显示哪些值,并且使用SELECT查询访问mytable似乎效率低下。 I was wondering if there's some way I could do something like this in that sub-query: 我想知道是否可以通过某种方式在子查询中执行以下操作:

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

I'm using an older version of Oracle where WITH clauses do not work. 我使用的Oracle旧版本中WITH子句不起作用。

You would have to get them as different rows, not different columns. 您将不得不将它们作为不同的行,而不是不同的列。 So you'll end up with 所以你最终会

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

In that case, the query should be equivalent as long as there are rows in mytable with fields 'A' and 'B'. 在这种情况下,只要mytable中的行具有字段“ A”和“ B”,该查询就应该等效。 If ever there aren't, then your subquery will return rows that the original subquery would not. 如果没有,那么您的子查询将返回原始子查询不会返回的行。

Why don't you upgrade your Oracle Version? 为什么不升级Oracle版本? The with-clause is added first to Oracle 9.2 (2002). 该从句首先添加到Oracle 9.2(2002)中。 Are you still using Oracle 8? 您还在使用Oracle 8吗?

You don't have a join between the FIELDS sub-query and MYTABLE, so your resultset will contain a row for every value of MYFIELD for the last thirty days. 您在FIELDS子查询和MYTABLE之间没有联接,因此您的结果集将为过去三十天的MYFIELD的每个值包含一行。

However, rather than adding that join, why not ditch the sub-query and just filter on MYTABLE.MYFIELD? 但是,为什么不放弃该子查询而不是添加该联接,而仅对MYTABLE.MYFIELD进行过滤? Also, if you are concerned about performance you should bound the date in a WHERE clause, otherwise you will process every row in MYTABLE. 另外,如果您担心性能,则应将日期绑定在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
/

edit 编辑

I have run your original query and my revised one against some test data. 我已经对一些测试数据运行了您的原始查询,并修改了我的查询。 You will just have to take my word for it that the two resulsets were in fact identical - or try it yourself :) 您只需要相信我的话,两个转义实际上是相同的-或自己尝试:)

Your query returns: 您的查询返回:

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>

My query returns: 我的查询返回:

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>

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

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