Oracle组太长时间了

时间:2011-07-07 10:38:42

标签: sql oracle group-by ora-00979

我有这个查询:

  SELECT B.BILL_BALANCE,
       B.PRIME_UID,
       home.IDENT,
       PRESENT.ACC_LOGIN,
       PRESENT.ACCOUNT_NAME2,
       eq .ACCESS_NO AS PHONE,
           adres.DISP_STREET_NAME,
           B.BILL_DT
FROM addresses adres ,
     BILL_HISTORY B
LEFT JOIN eq eq ON eq.ACCOUNT_NO = B.ACCOUNT_NO
JOIN sec PRESENT ON B.ACCOUNT_NO = PRESENT.ACCOUNT_NO
JOIN sec_text home ON home.ACCOUNT_NO = B.ACCOUNT_NO
WHERE eq.STATUS_CD = 'CU'
  AND (B.BILL_TP_CD='CB'
       OR B.BILL_TP_CD='FB')
  AND (PRESENT.bill_addr_UID=adres.PRIME_UID
       OR PRESENT.COMPANY_REG_ADDR_UID=adres.PRIME_UID)
  AND B.BILL_PAID_DT IS NULL
  AND B.BILL_DT >= to_date('2011-07-01')
  AND B.BILL_DT <= to_date('2011-07-02')
  AND rownum <=1000
GROUP BY B.PRIME_UID,
         B.BILL_BALANCE,
         home.IDENT,
         PRESENT.ACC_LOGIN,
         PRESENT.ACCOUNT_NAME2,
         eq .ACCESS_NO,
             adres.DISP_STREET_NAME,
             B.BILL_DT

在我遇到这个错误之后,我需要由B.PRIME_UID“分组”:

    [code] => 979
    [message] => ORA-00979: not a GROUP BY expression
    [offset] => 8

我将所有列添加到“分组依据”并且有效。

此查询仅适用于“rownum”。当我尝试删除“rownum”时 - 接近数据太长了...超过50分钟..

如何在不使用rowcount的情况下重写sql? 感谢。

表中的近似数据超过100 000.

已更新*
“解释计划”没有用。

Array
(
    [error] => 1
    [error text] => not found
    [sql] => EXPLAIN PLAN FOR
SELECT  B.BILL_BALANCE,B.PRIME_UID,home.IDENT,PRESENT.ACC_LOGIN,PRESENT.ACCOUNT_NAME2,eq .ACCESS_NO as PHONE,adres.DISP_STREET_NAME,B.BILL_DT
FROM addresses adres ,BILL_HISTORY B 
     LEFT JOIN eq eq ON eq.ACCOUNT_NO = B.ACCOUNT_NO 
     JOIN   sec PRESENT
         ON B.ACCOUNT_NO = PRESENT.ACCOUNT_NO
     JOIN sec_text home
         ON home.ACCOUNT_NO = B.ACCOUNT_NO



WHERE  
eq.STATUS_CD = 'CU'  AND
 (B.BILL_TP_CD='CB' OR B.BILL_TP_CD='FB') 
AND  (PRESENT.bill_addr_UID=adres.PRIME_UID OR PRESENT.COMPANY_REG_ADDR_UID=adres.PRIME_UID) 
AND B.BILL_PAID_DT IS NULL 
 AND B.BILL_DT >= to_date('2011-07-01') 
 AND B.BILL_DT <= to_date('2011-07-02') 

AND rownum <=10
GROUP BY B.PRIME_UID,B.BILL_BALANCE,home.IDENT,PRESENT.ACC_LOGIN,PRESENT.ACCOUNT_NAME2,eq .ACCESS_NO,adres.DISP_STREET_NAME,B.BILL_DT
)

3 个答案:

答案 0 :(得分:3)

你不仅在latrep.ADDRESSES和BILL_HISTORY之间有一个笛卡尔积,这很可能会破坏你的查询的性能,但是你也忽略了为你的TO_DATE函数指定日期格式 而不是:AND B.BILL_DT&gt; = to_date('2011-07-01')

使用:AND B.BILL_DT&gt; = to_date('2011-07-01','YYYY-MM-DD')

限制通过指定rownum&lt; = 10返回的记录的事实很快就会返回但是删除它会导致您的性能问题告诉我它正在尝试返回大量记录(笛卡尔积)或者您的执行计划有一些严重的问题,可能是大表的全表(或大索引范围)扫描。

无论哪种方式,如果无法生成解释计划,测试此方法的最佳方法是暂时从查询中删除表BILL_HISTROY,以查看性能是否增加,如果已识别问题。

整理这两个表之间的连接,它肯定会有所帮助。给我们一个解释计划,我们可以给你一个更明确的答案。

答案 1 :(得分:2)

没有解释计划很难肯定,但我认为问题与此有关:

FROM latrep.ADDRESSES adres ,
     BILL_HISTORY B

你那里有笛卡尔积。在没有连接条件的情况下,它会将ADDRESSES中的每一行连接到BILL_HISTORY中的每一行,除了所有其他连接之外。这将使它永生。稍后您会尝试将其缩小,但我怀疑OR会导致它必须先进行全表扫描和笛卡尔积,然后才能满足任何条件:

  AND (SUB.bill_addr_UID=adres.PRIME_UID
       OR SUB.COMPANY_REG_ADDR_UID=adres.PRIME_UID)

尝试完全从查询中提取BILL_HISTORY,看看性能是否有显着提升。如果是这样,那可能就是你的问题所在。 (然后去看你的DBA让EXPLAIN PLAN工作,解决这类问题真的是必要的。)

答案 2 :(得分:1)

我认为加入

有一个被遗忘的条件
latrep.ADDRESSES adres 

BILL_HISTORY B

这就是为什么它需要太长时间。

并且你只能在你的select子句(查询的一部分)中直接拥有group by子句中的内容。如果您不希望/需要按其他列分组,则不应该在那里进行分组。您应该根据需要使用max,min,avg,...聚合函数作为其值。

e.g。

select date_in, 
       min(id) as ids_from, 
       max(id) as ids_to
  from table
 group by date_in;