有没有如何使用2个内部联接优化查询到同一个表?

时间:2012-05-26 00:37:55

标签: sql sqlite

我有这个问题: 我有一个包含这3个表的模型: Linha,Itinerario和Rua 进入Itinerario我有Linha表的引用id和一个带有ru的id的引用。 在我的代码中,我收到两个关于idRua的论点,我必须返回所有Linhas,其中我有Itinerario与两个idRua的Rua的引用...在这个例子中我有idRua = 1和idRua = 2.

SELECT l.codigo, l.linha, l.idEmpresa, l.idLinha 
FROM Linha l 
INNER JOIN Itinerario i1 ON i1.idLinha = l.idLinha 
INNER JOIN Itinerario i2 ON i2.idLinha = l.idLinha 
WHERE i1.ida = i2.ida and i1.idRua = 1 and i2.idRua = 2 
ORDER BY l.linha

问题是我在该表Itinerario中得到2个内连接并且查询变慢... 有什么方法可以优化吗? 是否有一些“IN”运算符具有“AND”条件或类似的东西? 我正在使用SQLite。

3 个答案:

答案 0 :(得分:3)

可能有办法消除自我加入。

如果我正确地读到这个,你想要来自Itinerario的idLinha包含同一个ida的idRua = 1和idRua = 2。我注意到这只是一个过滤条件,因为select中的所有内容都来自linha。

以下是这种情况:

SELECT idlinha
From itinerario
GROUP BY idlinha, ida
having max(case when idRua = 1 then 1 else 0 end) = 1 and
       max(case when idRua = 2 then 1 else 0 end) = 1

现在,我们可以在“in”或“join”子句中使用它,如:

SELECT l.codigo, l.linha, l.idEmpresa, l.idLinha 
FROM Linha l
where l.idlinha in (SELECT idlinha
                    From itinerario
                    GROUP BY idlinha
                    having max(case when idRua = 1 then 1 else 0 end) = 1 and
                           max(case when idRua = 2 then 1 else 0 end) = 1
                   )
order by l.linha

group by可能比自联接更快。

答案 1 :(得分:2)

您的查询表达效果最佳。您需要确保具有正确的索引,以便SQLite有效地执行查询。确保Itinerario表的idLinha列中存在索引:

create index Itinerario_Linha_Idx on Itinerario(idLinha)

idRua上的索引也可以派上用场:

create index Itinerario_Rua_Idx on Itinerario(idRua)

答案 2 :(得分:2)

由于您的WHERE条件不适用于表Linha,因此您可以通过将条件移动到相关的ON子句中来提高性能,其中它们可以作为内部联接应用正在制作,而不是在结果集上:

SELECT l.codigo, l.linha, l.idEmpresa, l.idLinha 
FROM Linha l 
INNER JOIN Itinerario i1 ON i1.idLinha = l.idLinha and i1.idRua = 1
INNER JOIN Itinerario i2 ON i2.idLinha = l.idLinha and i2.idRua = 2 and i1.ida = i2.ida
ORDER BY l.linha

此外,您必须拥有Itinerario(idLinha)的索引。 Itinerario(idRua)的索引几乎肯定无济于事。

为了获得上述查询的最佳效果,请在 idLinhaidRua上创建索引:

create index Itinerario_Index1 on Itinerario(idLinha, idRua);

idLinha子句中同时使用idRuaON,可以使用索引的两个部分,因此数据库只会读取所需的确切行,最小化I / O.