【问题标题】:Re-writing EXISTS as JOIN or a subquery in Oracle在 Oracle 中将 EXISTS 重写为 JOIN 或子查询
【发布时间】:2021-04-23 13:59:55
【问题描述】:

我有一个非常昂贵的查询,并且需要一个多小时才能执行。我尝试将 EXISTS 子句转换为加入,但我卡住了,有人可以帮忙吗?

目的是在唯一的空间 id 中查找重复的产品。 FLAT_TABLE 包含 500 万条记录。

查询:

 select
    tbl1.product,
    tbl1.status,
    tbl1.reservation,
    tbl1.unique_space_id
FROM
    schema1.flat_table tbl1
WHERE
    tbl1.status = 'Active'
    AND tbl1.product = 'Cage'
    AND EXISTS
        (SELECT 1
        FROM schema1.flat_table tbl2
        WHERE tbl2.product = 'Cage'
        AND tbl2.status = 'Active'
        AND tbl2.reservation <> 'Space Reserved'
        AND tbl1.unique_space_id = tbl2.unique_space_id
        GROUP BY tbl2.unique_space_id
        HAVING COUNT (1) > 1
        );

【问题讨论】:

    标签: sql oracle performance exists


    【解决方案1】:

    您可以使用解析函数count如下:

    select * from
    (select tbl1.product, tbl1.status, tbl1.reservation, tbl1.unique_space_id,
            count(case when tbl1.reservation <> 'Space Reserved' then 1 end) 
             over(partition by tbl1.unique_space_id) as cnt 
      FROM schema1.flat_table tbl1  
     WHERE tbl1.status = 'Active' AND tbl1.product = 'Cage')
     where cnt > 1
    

    【讨论】:

    • 这真的有效,谢谢。但我现在想避免分析功能。 @Tim Biegeleisen 建议的内部连接工作得很好。
    • 很高兴听到它对您有所帮助。 :)
    • @MohammedArif 。 . .为什么要避免使用窗口功能。它们更简洁,并且几乎总是比替代品具有更好的性能。
    【解决方案2】:

    您可以将查询重写为当前存在子查询的内部联接。连接的过滤效果与 exists 子句的行为方式相同。

    SELECT DISTINCT
        tbl1.product,
        tbl1.status,
        tbl1.reservation,
        tbl1.unique_space_id
    FROM schema1.flat_table tbl1
    INNER JOIN
    (
        SELECT unique_space_id
        FROM schema1.flat_table
        WHERE product = 'Cage' AND
              status = 'Active' AND
              reservation <> 'Space Reserved'
        GROUP BY unique_space_id
        HAVING COUNT(*) > 1
    ) tbl2
        ON tbl2.unique_space_id = tbl1.unique_space_id
    WHERE
        tbl1.status = 'Active' AND
        tbl1.product = 'Cage';
    

    这是一个更简洁的版本,使用COUNT 作为解析函数,以及QUALIFY 子句;

    SELECT DISTINCT product, status, reservation, unique_space_id
    FROM schema1.flat_table
    WHERE status = 'Active' AND product = 'Cage'
    QUALIFY COUNT(CASE WHEN reservation <> 'Space Reserved' THEN 1 END) 
            OVER (PARTITION BY unique_space_id) > 1;
    

    【讨论】:

    • 这就是我想要的。 :-)
    • 我对堆栈溢出非常陌生,并且声誉低于 15,所以实际上我的投票不会添加绿色复选标记。但是,我赞成哪个记录在案。
    猜你喜欢
    • 2014-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-04
    • 2011-05-14
    • 1970-01-01
    • 1970-01-01
    • 2010-12-08
    相关资源
    最近更新 更多