如何使用max in where子句优化Oracle中的查询

时间:2015-09-03 13:30:41

标签: oracle query-optimization

我提供假设的表格和查询来解释我的问题。请原谅我任何sntax错误。

部门表:

ID Dno Dname BDate   seq
1  1     A    5-Aug   0
2  1     B    3-Aug   0
3  1     B    7-Aug   1
4  1     C    2-Aug   0

以下查询从上表返回第1和第3条记录:

select * from Dept where BDate > (select mydate from other_table)
-- mydate is 4-Aug

然后我在查询中进行了以下更改以返回第二条记录。因为对于Dname'B',我们有一个记录与Bdate> 4 - 译者:

select * from Dept D where
(SELECT MAX(BDATE)
FROM Dept D1
WHERE D1.Dno = D.Dno
AND D1.Dname = D.Dname
) > (select mydate from other_table)

以上查询有效,但达到了性能。我怎么能优化它。

我想到Union或移动max查询来选择部分。但是,找不到办法。

5 个答案:

答案 0 :(得分:1)

假设我正确理解你的逻辑(如果最大日期大于指定日期你想要给定dno和dname的所有行)并且检索“mydate”的查询返回单行,我会这样做类似的东西:

with     dept as (select 1 id, 1 dno, 'A' dname, to_date('05/08/2015', 'dd/mm/yyyy') bdate, 0 seq from dual union all
                  select 2 id, 1 dno, 'B' dname, to_date('03/08/2015', 'dd/mm/yyyy') bdate, 0 seq from dual union all
                  select 3 id, 1 dno, 'B' dname, to_date('07/08/2015', 'dd/mm/yyyy') bdate, 0 seq from dual union all
                  select 4 id, 1 dno, 'C' dname, to_date('02/08/2015', 'dd/mm/yyyy') bdate, 0 seq from dual),
  other_table as (select to_date('04/08/2015', 'dd/mm/yyyy') mydate from dual)
select id,
       dno,
       dname,
       bdate,
       seq
from   (select d.*,
               max(bdate) over (partition by dno, dname) max_bdate
        from   dept d)
where  max_bdate > (select mydate from other_table);

        ID        DNO DNAME BDATE             SEQ
---------- ---------- ----- ---------- ----------
         1          1 A     05/08/2015          0
         2          1 B     03/08/2015          0
         3          1 B     07/08/2015          0

答案 1 :(得分:0)

使用group-by子句避免其中一个子查询:

select Dno, Dname, max(BDate)
from Dept
group by Dno, Dname
having Max(BDate) > (select mydate from other_table)

您还可以使用本地var:

删除其他子查询
declare @mydate Date = (select mydate from other_table);
select Dno, Dname, max(BDate)
from Dept
group by Dno, Dname
having Max(BDate) > (@mydate)

答案 2 :(得分:0)

如果您希望此查询返回An error was discovered processing the <wsse:Security> header. at org.apache.axis.message.SOAPFaultBuilder.createFault(SOAPFaultBuilder.java:222) at org.apache.axis.message.SOAPFaultBuilder.endElement(SOAPFaultBuilder.java:129) at org.apache.axis.encoding.DeserializationContext.endElement(DeserializationContext.java:1087) at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:609) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1782) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2973) at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606) at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:117) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777) at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141) at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213) at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:649) at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl.parse(SAXParserImpl.java:333) at org.apache.axis.encoding.DeserializationContext.parse(DeserializationContext.java:227) at org.apache.axis.SOAPPart.getAsSOAPEnvelope(SOAPPart.java:696) at org.apache.axis.Message.getSOAPEnvelope(Message.java:435) at org.apache.axis.handlers.soap.MustUnderstandChecker.invoke(MustUnderstandChecker.java:62) 表中的一小部分行,则这可能会更快。我假设DEPT是唯一的,并且有一个索引。 (当然,DEPT.DNAME需要有一个索引!)

DEPT.BDATE

答案 3 :(得分:0)

以下查询运行速度快4倍,结果正确:

select d1.* from Dept d1,
(select dno, dname, MAX(BDATE) as maxdate from Dept group by dno, dname) d2
where
d1.dno=d2.dno and d1.dname=d2.dname
and d2.maxdate > (select mydate from other_table)

答案 4 :(得分:0)

根据数据集的选择性,可能值得尝试这种方法:

select *
from   dept
where  (dno, dname) in (
         select distinct dno, dname
         from   dept
         where  BDATE > (select mydate from other_table))

使用dept(bdate)和dept(dno,dname)上的索引,并且只有少数匹配的记录,这将非常快。