解决SQL查询'不在'需要永远吗?

时间:2014-06-19 20:20:07

标签: sql oracle

我正在尝试在Oracle 10g数据库上运行查询以尝试查看2组事务。我想查看今年(2014年)有交易的任何人,这些交易在过去的5年中也有过交易。然后,我想对今年(2014年)有交易的人进行查询,该交易在过去5年内未从我们这里订购。我以为我可以用“IN”和“NOT IN”功能来做到这一点。 'IN'查询运行正常,但'NOT IN'永远不会完成。 DB相当大,这可能就是原因。非常喜欢专家的任何建议!

*注意事项,[TEXT]是我们客户公司名称的描述,有时会计部门没有将此与我们留下NULL值的客户ID联系起来,因此使用TEXT作为我的主要分组似乎有效,尽管名称是朦胧。 CODE_D是一个产品系列,只是为了为名称带来上下文。

以下是我的代码:

SELECT CODE_D, sum(coalesce(credit_amount, 0) - coalesce(debet_amount,0)) as TOTAL 
FROM 
gen_led_voucher_row_tab
WHERE ACCOUNTING_YEAR like '2014'
and TEXT NOT IN
    (select TEXT
    from gen_led_voucher_row_tab
    and voucher_date >= '01-JUN-09'
    and voucher_date < '01-JUN-14'
    and (credit_amount > '1' or debet_amount > '1')
    )
GROUP BY CODE_D
ORDER BY TOTAL DESC

2 个答案:

答案 0 :(得分:1)

尝试使用LEFT JOIN代替NOT IN

SELECT t1.CODE_D, sum(coalesce(t1.credit_amount, 0) - coalesce(t1.debet_amount,0)) as TOTAL
FROM gen_led_voucher_row_tab AS t1
LEFT JOIN gen_led_voucher_row_tab AS t2
ON t1.TEXT = t2.TEXT
    AND t2.voucher_date >= '01-JUN-09'
    AND t2.voucher_date < '01-JUN-14'
    AND (credit_amount > '1' or debet_amount > '1')
WHERE t2.TEXT IS NULL
    AND t1.ACCOUNTING_YEAR = '2014'
GROUP BY CODE_D
ORDER BY TOTAL DESC

另外,请确保TEXT列上有索引。

答案 1 :(得分:0)

您可以将Not In子句更改为Where Not Exists,如下所示,从而提高效果:

Where Not Exists
(
    Select  1
    From    gen_led_voucher_row_tab b
    Where   voucher_date >= '01-JUN-09'
    and     voucher_date < '01-JUN-14'
    and     (credit_amount > '1' or debet_amount > '1')
    And     a.Text = b.Text
)

您还需要将第一个表别名为a,以使其正常工作。从本质上讲,你正在撤回大量数据以丢弃它。 Exists调用Semi Join根本不会撤回任何数据,因此您应该看到显着的改进。

修改

您的查询,截至当前问题的更新应为:

SELECT  CODE_D, 
        sum(coalesce(credit_amount, 0) - coalesce(debet_amount,0)) as TOTAL 
FROM    gen_led_voucher_row_tab a
Where   ACCOUNTING_YEAR like '2014'
And Not Exists
(
    Select  1
    From    gen_led_voucher_row_tab b
    Where   voucher_date >= '01-JUN-09'
    and     voucher_date < '01-JUN-14'
    and     (credit_amount > '1' or debet_amount > '1')
    And     a.Text = b.Text
)
GROUP BY CODE_D
ORDER BY TOTAL DESC