3

我有一个 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

4 回答 4

12

标准 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通常应该避免,特别是如果你也有几个加入。

于 2011-03-29T09:32:37.450 回答
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;
于 2011-03-29T11:06:27.203 回答
2

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

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

于 2012-08-05T21:12:44.713 回答
0

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

我希望它有帮助

于 2011-03-29T09:33:17.367 回答