Al tratar de mejorar la velocidad de una consulta inmensamente lenta (varios minutos en dos tablas con solo ~ 50,000 filas cada una, en SQL Server 2008 si es importante), reduje el problema a una ORcombinación interna, como en:
SELECT mt.ID, mt.ParentID, ot.MasterID
FROM dbo.MainTable AS mt
INNER JOIN dbo.OtherTable AS ot ON ot.ParentID = mt.ID
OR ot.ID = mt.ParentID
Cambié esto a (lo que espero sea) un par equivalente de uniones izquierdas, que se muestran aquí:
SELECT mt.ID, mt.ParentID,
CASE WHEN ot1.MasterID IS NOT NULL THEN
ot1.MasterID ELSE
ot2.MasterID END AS MasterID
FROM dbo.MainTable AS mt
LEFT JOIN dbo.OtherTable AS ot1 ON ot1.ParentID = mt.ID
LEFT JOIN dbo.OtherTable AS ot2 ON ot2.ID = mt.ParentID
WHERE ot1.MasterID IS NOT NULL OR ot2.MasterID IS NOT NULL
.. y la consulta ahora se ejecuta en aproximadamente un segundo.
¿Es generalmente una mala idea poner un ORen una condición de unión? ¿O simplemente tengo mala suerte en el diseño de mis tablas?
sql
sql-server
sql-server-2008
tsql
inner-join
ladenedge
fuente
fuente

Respuestas:
Este tipo de
JOINno es optimizable para aHASH JOINo aMERGE JOIN.Puede expresarse como una concatenación de dos conjuntos de resultados:
, siendo cada uno de ellos un equijoin, sin embargo,
SQL Serverel optimizador no es lo suficientemente inteligente como para verlo en la consulta que escribió (aunque son lógicamente equivalentes).fuente
ON w=x OR y=zpatrón por completo.ON w=x OR y=z? (¡Gracias por tu paciencia!)SQL Servercomprender que se necesitaría una concatenación. Digamos que la consultaSELECT * FROM othertable WHERE parentId = 1 OR id = 2usará una concatenación si ambos campos están indexados, por lo que, en teoría, no hay nada que impida hacer lo mismo en un bucle. SiSQL Serverconstruiremos este plan o no, depende de muchos factores, pero nunca lo he visto construido en la vida real.Utilizo el siguiente código para obtener un resultado diferente de la condición que funcionó para mí.
fuente
En su lugar, puede utilizar UNION ALL.
SELECT mt.ID, mt.ParentID, ot.MasterID FROM dbo.MainTable AS mt Union ALL SELECT mt.ID, mt.ParentID, ot.MasterID FROM dbo.OtherTable AS otfuente
UNION ALLle dará duplicados en comparación conJOINcon unaORcondición.union allque no es correcto como también describe el artículo al que enlaza.