如何避免为IN子句重复此子查询?

时间:2011-03-29 09:26:39

标签: sql subquery dry in-clause

我有一个SQL脚本(目前针对SQLite运行,但它可能适用于任何数据库引擎),它使用相同的子查询两次,因为它可能会获取大量记录(该表有几百万行我只想打电话一次。

查询的缩短伪版本如下所示:

SELECT * FROM
    ([the subquery, returns a column of ids]) AS sq
[a couple of joins, that fetches things from other tables based on the ids]
WHERE thisorthat NOT IN ([the subquery again])

我尝试以各种方式使用名称(sq)(带/不带括号,有/无命名sq等列)但无效。

我真的重复这个子查询吗?

澄清: 我在python和sqlite中做这个,作为可以完成的小型演示,但我希望我的解决方案尽可能少地进行修改。在实际情况中,数据库将有几百万行,但在我的示例中,只有10行具有虚拟数据。因此,在例如MySQL 上进行了优化的代码是非常好的 - 它不必针对SQLite 进行优化。但正如我所说,需要的修改越少越好。

4 个答案:

答案 0 :(得分:8)

标准SQL中有一个WITH子句,但是,我不知道SQLlite是否支持它 - 虽然当然值得一试:

WITH mySubQuery AS
(
  [the subquery code]
)

SELECT * FROM
    mySubQuery AS sq
    [a couple of joins, that fetches things from other tables based on the ids]
WHERE thisorthat NOT IN (mySubQuery)

也就是说,对于任何超过几千行的数据集,你在这里所做的事情可能会非常慢,所以如果可能的话我会尝试重新构建它 - 一般应该避免使用NOT IN,特别是如果你也有几个连接。

答案 1 :(得分:5)

你需要子查询吗?您可以使用OUTER JOIN重写,例如类似的东西:

SELECT * 
  FROM [the subquery's FROM clause] AS sq
       RIGHT OUTER JOIN [a couple of tables based on the ids]
          ON thisorthat = sq.[a column of ids]
 WHERE sq.[a column of ids] IS NULL;

答案 2 :(得分:1)

总的来说,我质疑消除重复的必要性。 SQL编译器可以看到两个子查询是相同的,如果看起来最佳,则选择只执行一次。

此外,通过在源代码中保留重复项,SQL编译器和优化器有机会以不同方式对待它们。例如,SQLite的子查询展平优化可以应用于一对重复中的一个,或者对每个重复应用不同。请参见第9.0节,https://www.sqlite.org/optoverview.html的子查询扁平化。

答案 3 :(得分:0)

您可以将SELECT部分​​放入View中,而不是使用别名“sq”过滤View结果

我希望它有用