需要加快这个SQL语句的结果。有什么建议?

时间:2010-03-31 13:37:56

标签: sql subquery

我有以下需要大幅加速的SQL语句。问题是我需要搜索两个字段,其中每个字段都调用几个子选择。有没有办法将两个字段连接在一起,所以我只调用子选择一次?

SELECT billyr, billno, propacct, vinid, taxpaid, duedate, datepif, propdesc
FROM trcdba.billspaid
WHERE date(datepif) > '01/06/2009'
AND date(datepif) <= '01/06/2010'
AND custno in
 (select custno from cwdba.txpytaxid where taxpayerno in
  (select taxpayerno from cwdba.txpyaccts where accountno in
   (select accountno from rtadba.reasacct where controlno = 1234567)))
OR custno2 in
 (select custno from cwdba.txpytaxid where taxpayerno in
  (select taxpayerno from cwdba.txpyaccts where accountno in
   (select accountno from rtadba.reasacct where controlno = 1234567)))

4 个答案:

答案 0 :(得分:13)

我会使用连接而不是嵌入式子查询。

答案 1 :(得分:6)

使用JOIN代替子查询也是一样。

SELECT billyr, billno, propacct, vinid, taxpaid, duedate, datepif, propdesc
FROM billspaid
INNER JOIN txpytaxid
  ON txpytaxid.custno = billspaid.custno OR txpytaxid.custno = billspaid.custno2
INNER JOIN txpyaccts
  ON txpyaccts.taxpayerno = txpytaxid.taxpayerno
INNER JOIN reasacct
  ON reasacct.accountno = txpyaccts.accountno AND reasacct.controlno = 1234567
WHERE date(datepif) > '01/06/2009'
  AND date(datepif) <= '01/06/2010'

但是,如果JOIN中的OR给您带来性能问题,您可以尝试使用union:

(SELECT billyr, billno, propacct, vinid, taxpaid, duedate, datepif, propdesc
FROM billspaid
INNER JOIN txpytaxid
  ON txpytaxid.custno = billspaid.custno
INNER JOIN txpyaccts
  ON txpyaccts.taxpayerno = txpytaxid.taxpayerno
INNER JOIN reasacct
  ON reasacct.accountno = txpyaccts.accountno AND reasacct.controlno = 1234567
WHERE date(datepif) > '01/06/2009'
  AND date(datepif) <= '01/06/2010')
UNION
(SELECT billyr, billno, propacct, vinid, taxpaid, duedate, datepif, propdesc
FROM billspaid
INNER JOIN txpytaxid
  ON txpytaxid.custno = billspaid.custno2
INNER JOIN txpyaccts
  ON txpyaccts.taxpayerno = txpytaxid.taxpayerno
INNER JOIN reasacct
  ON reasacct.accountno = txpyaccts.accountno AND reasacct.controlno = 1234567
WHERE date(datepif) > '01/06/2009'
  AND date(datepif) <= '01/06/2010')

答案 2 :(得分:6)

在列上使用函数时:

date(datepif) > '01/06/2009'
AND date(datepif) <= '01/06/2010'

不会使用索引。试试这样的事情

datepif > someconversionhere('01/06/2009')
AND datepif <= someconversionhere('01/06/2010')

也使用内连接。问题中没有任何信息表明表格大小或者是否有索引,所以这是一个猜测,如果日期范围的billpaid中有更多行与匹配表格匹配的行,则应该效果最佳对于r.controlno = 1234567,我怀疑是这样的:

SELECT 
    COALESCE(b1.billyr,b2.billyr)           AS billyr
        ,COALESCE(b1.billno,b2.billno)      AS billno
        ,COALESCE(b1.propacct,b2.propacct)  AS propacct
        ,COALESCE(b1.vinid,b2.vinid)        AS vinid
        ,COALESCE(b1.taxpaid,b2.taxpaid)    AS taxpaid
        ,COALESCE(b1.duedate,b2.duedate)    AS duedate
        ,COALESCE(b1.datepif,b2.datepif)    AS datepif
        ,COALESCE(b1.propdesc,b2.propdesc)  AS propdesc
    FROM rtadba.reasacct                  r
        INNER JOIN cwdba.txpyaccts        a ON r.accountno=t.accountno
        INNER JOIN cwdba.txpytaxid        t ON a.taxpayerno=t.taxpayerno
        LEFT OUTER JOIN trcdba.billspaid b1 ON t.custno=b1.custno AND b1.datepif > someconversionhere('01/06/2009') AND b1.datepif <= someconversionhere('01/06/2010')
        LEFT OUTER JOIN trcdba.billspaid b2 ON t.custno2=b2.custno AND b2.datepif > someconversionhere('01/06/2009') AND b2.datepif <= someconversionhere('01/06/2010')
    WHERE r.controlno = 1234567
      AND COALESCE(b1.custno,b2.custno) IS NOT NULL

为每个创建一个索引:

rtadba.reasacct.controlno and cover on accountno
cwdba.txpyaccts.accountno and cover on taxpayerno
cwdba.txpytaxid.taxpayerno and cover on custno
trcdba.billspaid.custno +datepif
trcdba.billspaid.custno2 +datepif

答案 3 :(得分:0)

使用EXISTS代替IN(除非IN子查询的结果集非常小)。

如果您使用UNION而不是OR(应该在功能上等效),请使用UNION ALL。