【问题标题】:How can I replace `SELECT ... WHERE SELECT ...` with joins?如何用连接替换`SELECT ... WHERE SELECT ...`?
【发布时间】:2013-07-15 16:01:18
【问题描述】:

我读到SELECT ... WHERE SELECT ... 很慢,我应该改用连接。

但我不知道如何替换这段代码

SELECT Id
FROM Table1
Where
    (
        Data1 IS NULL
        OR
        (
            Data2=1
            AND
            (SELECT 1 FROM Table2 WHERE Table2.Id=Table1.Id) IS NULL
        )
    )
    AND
    (SELECT 1 FROM Table3 WHERE Table3.Id=Table1.Id) IS NULL

有连接。

这些表的结构如下:

表1:

  • ID:整数主键
  • 数据1:XML
  • 数据2:整数

表2:

  • ID:整数

表3:

  • ID:整数主键

【问题讨论】:

  • PDO 帮不了你。
  • 首先查看 EXPLAIN 以查看是否存在优化器未解决的问题 - 然后您可以担心调整 - 而不是尝试遵循全局规则。
  • @Randy 我从来不明白如何使用 EXPLAIN。如果我只是在查询之前写 EXPLAIN 并在 phpliteadmin 上运行它,它只会说“0 行受影响
  • @CL。当我运行 EXPLAIN QUERY PLAN 时,我也得到“0 行受影响”,没有结果

标签: sql sqlite select join


【解决方案1】:
select Id from Table1 where
  Id not in (select Id from Table3) and
  (Data1 is null or 
   (Data2 = 1 and Id not in (select Id from Table2)));

或者,如果你真的想要加入:

select Id from Table1 left join Table2 on (Table1.Id = Table2.Id)
  left join Table3 on (Table1.Id = Table3.Id)
where Table3.Id is null and
  (Data1 is null or
   (Data2 = 1 and Table2.Id is null));

我预计这两者之间的性能差异不会很大。该查询可能会受益于 Table2.Id 上的索引(您在 Table3.Id 上有一个索引,因为它是主键)。

【讨论】:

  • 谢谢!但是在Table2上创建索引后,Id not in (select Id from Table2)不使用它,但not exists (select 1 from Table2 where Table2.Id=Table1.Id)使用它,而且它似乎与joins花费相同的时间
【解决方案2】:

将子查询从in 移动到from 子句有两个关键部分。第一种是使用left outer join,因此第一个表中的行不会意外丢失。第二种是对每个子查询使用select distinct,以避免不必要的重复。

应用于您的查询,结果为:

SELECT t1.Id
FROM Table1 t1 left outer join
     (select distinct id
      from Table2
     ) t2
     on t1.id = t2.id left outer join
     (select distinct id
      from Table3
     ) t3
     on t1.id = t3.id
Where(t1.Data1 IS NULL OR
      (t1.Data2=1 and t2.id is null)
     ) and
     t3.id is null;

【讨论】:

  • 当我运行你的代码时,我得到 "ERROR: near "from": syntax error"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-19
  • 1970-01-01
  • 2012-11-17
  • 1970-01-01
  • 1970-01-01
  • 2016-10-11
  • 1970-01-01
相关资源
最近更新 更多