2012-09-17 72 views
0

我的用例是检索客户的发票和每张发票的格式代码,这些代码是通过加入到customer_list表中的加入找到的,该表加入到通用代码表以计算格式代码。如何优化嵌套选择?

我的查询的简化版本如下,它工作正常,但子查询将返回大约5k行,我不知道如何优化,以便子查询不包含尽可能多的行。

select i.invoice_number, 
     f.format_code 
    from invoices i 
    left join (
    select gc.code_1 as format_code, 
      ls.account 
     from gen_codes gc, 
      customer_list ls 
    where gc.code_name = 'invoice-format' 
     and gc.code_1 <> '' 
     and ls.list_type = gc.code_value 
) f on account = i.account 
     or account = i.billing_account 
where i.account = :accountNumber 

注意:并非所有的发票有一个格式代码,这是很好的,为什么我执行左连接。

UPDATE:不使用内部的选择将是以下形式的类似查询:

select i.invoice_number, 
     f.code_1 as format_code 
    from invoices i 
    left join customer_list ls on 
    (account = i.account or account = i.billing_account) and ls.list_type in (
      select code_value 
      from gen_codes 
      where code_name = 'invoice-format' 
       and code_1 <> '' 
     ) 
    left join gen_codes f on code_value = ls.list_type 
         and code_name = 'invoice-format' 
         and code_1 <> '' 

我有一种感觉,这后一种版本可能是因为有在gen_codes只有二十几记录更有效与匹配的查询,而customer_list包含约50万记录与〜5K匹配的第一个版本。

+0

为了帮助我更好地理解内部选择语句,SQL引擎如何解释这一点?他们是否在外部选择语句之前执行内部选择?如果是这样的话,这个结果会在选择的其余部分被重用,所以它只会被执行一次? –

回答

0

如下我会写:

获取所有对应一个账户或结算账户(使用JOIN和ON子句)的发票,只有匹配该帐户的list_types有关的gen_codes(使用LEFT JOIN得到)其code_name为'invoice-format'且gc.code_1不为空。

SELECT 
    i.invoice_number, 
    gc.code_1 as format_code 
FROM 
    invoices i 
    JOIN customer_list ls 
    ON 
     (i.billing_account = ls.account OR i.account = ls.account) AND 
     i.account = :accountNumber 
    LEFT JOIN gen_codes gc 
    ON 
     ls.list_type = gc.code_value AND 
     gc.code_name = 'invoice-format' AND 
     gc.code_1 != '' 

这将修剪不中了accountNumber输入前期相比,在你的问题的子查询匹配CUSTOMER_LIST记录。

+0

客户可能没有列表类型的'gen_codes'条目,我希望'NULL'返回''format_code'在我的查询中正常工作。 gen_codes的连接将因此将这些关闭。 –

+0

另请注意,由于客户可能出现在多个与发票格式列表无关的列表中,因此将“gen_codes”加入“left join”不起作用。 –

+0

可否请你看看修改的查询(我试图描述我打算用查询做什么,在它上面),当你有机会吗?基本思想是使用帐号过滤器修剪customer_list记录。 – Vikdor