我有一个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 进行优化。但正如我所说,需要的修改越少越好。
答案 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结果
我希望它有用