【问题标题】:SQL Statement - optimisationSQL 语句 - 优化
【发布时间】:2012-12-14 18:39:03
【问题描述】:

我有这样的声明:

SELECT *
  FROM sgtn
 WHERE sgtn_kun_id IN (SELECT DISTINCT kun_id
                         FROM sgtn, kun
                        WHERE kun.kun_e_mail IN (LONG LIST OF EMAILS)
                              AND sgtn_kun_id = kun_id)

       AND sgtn_strasse IN (SELECT sgtn.sgtn_strasse
                              FROM sgtn
                             WHERE sgtn_kun_id IN (SELECT DISTINCT kun_id
                                                     FROM sgtn, kun
                                                    WHERE kun.kun_e_mail IN (LONG LIST OF EMAILS)
                                                          AND sgtn_kun_id = kun_id)

                             GROUP BY sgtn.sgtn_strasse
                            HAVING COUNT(sgtn_strasse) > 2);

LONG LIST OF EMAILS 即: 'abc@domain.com', 'def@domain.com', . . . 'xyz@domain.com'

如您所见,我在此查询中重复了部分子查询。

我想知道是否以及如何替换LONG LIST OF EMAILS。它在我的陈述中出现了两次。是否可以编辑此查询,以便提到的LONG LIST OF EMAILS 出现一次?

【问题讨论】:

  • 用连接替换你的子查询和IN,在这种情况下它们可以达到相同的结果并且更加更有效率。一旦你知道它们是如何工作的,也会更容易。
  • 另外:为什么这些电子邮件会直接出现在您的查询中?它们不是存储在同一个数据库中吗?如果您的查询应该检索它们,而不是包含它们文字
  • 你能解释一下使用上面的查询试图返回什么吗?
  • @dtech:带有 IN 的连接和子查询不等效。
  • 您仍然可以使用 JOIN(WHERE 等...)来做到这一点,但如果您只是提供

标签: sql oracle


【解决方案1】:

使用 WITH 子句:

WITH kun_list AS (
    SELECT DISTINCT kun_id
      FROM sgtn, kun
     WHERE kun.kun_e_mail IN (LONG LIST OF EMAILS)
           AND sgtn_kun_id = kun_id)

SELECT *
  FROM sgtn
 WHERE sgtn_kun_id IN (SELECT kun_id
                         FROM kun_list)

       AND sgtn_strasse IN (SELECT sgtn.sgtn_strasse
                              FROM sgtn
                             WHERE sgtn_kun_id IN (SELECT kun_id
                                                     FROM kun_list)

                             GROUP BY sgtn.sgtn_strasse
                            HAVING COUNT(sgtn_strasse) > 2);

【讨论】:

  • 这会(正确地)响应电子邮件列表重复,但不会提高性能,因为它与 OP 中的查询基本相同。
【解决方案2】:

首先,你不需要使用

IN (SELECT DISTINCT kun_id
    FROM sgtn, kun
    WHERE kun.kun_e_mail IN (LONG LIST OF EMAILS)
    AND sgtn_kun_id = kun_id)

够了

IN (SELECT kun_id
    FROM kun
    WHERE kun.kun_e_mail IN (LONG LIST OF EMAILS))

列表中包含多个 sgtn_strasse 和 email 的行可以通过

检测到
select * from (
  SELECT s.*, count(*) over (partition by sgtn_strasse) cnt_strasse
  FROM sgtn s
  WHERE sgtn_kun_id IN (SELECT kun_id
                       FROM kun
                       WHERE kun.kun_e_mail IN (LONG LIST OF EMAILS))
  )
WHERE cnt_strasse > 1;

【讨论】:

    【解决方案3】:

    你可以试试这个:

    with CTE as (
    SELECT sgtn.*, count(sgtn_strasse) OVER (PARTITION BY sgtn_strasse) cnt
    FROM sgtn
    WHERE sgtn_kun_id IN (SELECT kun_id FROM kun 
                          WHERE kun.kun_e_mail IN (LONG LIST OF EMAILS))
    )
    
    SELECT * FROM  CTE WHERE CNT > 2
    

    【讨论】:

    • 要纠正两件事:sgtn_kun_id IN (SELECT * 部分和 cte 中没有列 kun_id。
    • 现在好了,和我的答案基本一样:)
    猜你喜欢
    • 1970-01-01
    • 2012-05-10
    • 1970-01-01
    • 2013-03-07
    • 1970-01-01
    • 1970-01-01
    • 2019-12-31
    • 2015-11-27
    • 2015-04-27
    相关资源
    最近更新 更多