2010-09-02 16 views
5

He cambiado los nombres de las tablas, pero encontré esta declaración FROM en un SP que estoy optimizando y me pregunto cómo podría surgir esto, por qué harías algo así y por qué funciona. .¿Alguien puede entender por qué hacer esto o cómo funciona correctamente con este bit de SQL?

FROM   tblPezFill pf 
RIGHT OUTER JOIN tblWolveLocation stfl 
RIGHT OUTER JOIN tblDuckPez pp 
RIGHT OUTER JOIN tblChaos o 
INNER JOIN tblBillLeg bi 
INNER JOIN @Facty selFac 
ON bi.WolveId = selFac.WolveId 
ON o.ChaosID = bi.ChaosId 
LEFT OUTER JOIN vwDonald stPres 
RIGHT OUTER JOIN tblStockChaos so 
      ON stPres.DonaldId = so.DonaldId 
      ON o.StockChaosID = so.StockChaosID 
      ON pp.PezID = o.PezID 
      ON stfl.WolveLocationId = so.WolveLocationId 
      ON pf.PezFillID = o.PezFillID 
LEFT OUTER JOIN tblCheeseburger p ON bi.CheeseburgerId = p.CheeseburgerId 
LEFT OUTER JOIN tblChaosCheeseburgerShipped ops ON o.ChaosID = ops.ChaosID 
LEFT OUTER JOIN vwDonald pres ON pp.DonaldId = pres.DonaldId 
LEFT OUTER JOIN tblDuck ON pp.DuckID = tblDuck.DuckId 
LEFT OUTER JOIN vwDuck ON pp.DuckID = vwDuck.DuckId 
LEFT OUTER JOIN tblWolveLocation fl ON pf.WolveLocationId = fl.WolveLocationId 

He limpiado hasta

FROM tblBillLeg bi 
INNER JOIN @Facty selFac ON bi.WolveId = selFac.WolveId 
LEFT OUTER JOIN tblCheeseburger p ON bi.CheeseburgerId = p.CheeseburgerId 
LEFT OUTER JOIN tblChaos o ON o.ChaosID = bi.ChaosId 
LEFT OUTER JOIN tblDuckPez pp ON pp.PezID = o.PezID 
LEFT OUTER JOIN tblPezFill pf ON pf.PezFillID = o.PezFillID 
LEFT OUTER JOIN tblChaosCheeseburgerShipped ops ON o.ChaosID = ops.ChaosID 
LEFT OUTER JOIN tblStockChaos so ON o.StockChaosID = so.StockChaosID 
LEFT OUTER JOIN tblWolveLocation stfl ON stfl.WolveLocationId = so.WolveLocationId 
LEFT OUTER JOIN vwDonald stPres ON stPres.DonaldId = so.DonaldId 
LEFT OUTER JOIN vwDonald pres ON pp.DonaldId = pres.DonaldId 
LEFT OUTER JOIN tblDuck ON pp.DuckID = tblDuck.DuckId 
LEFT OUTER JOIN vwDuck ON pp.DuckID = vwDuck.DuckId 
LEFT OUTER JOIN tblWolveLocation fl ON pf.WolveLocationId = fl.WolveLocationId 

que creo que debe ser equivalente, necesito algunos datos de prueba. Simplemente no entiendo cómo la primera versión realmente funcionó.

+1

+1: Para código antiguo fugly. Desearía que SQL Server hiciera una mejor verificación de sintaxis para la cláusula 'ON '. ¿Esto es en 2005, 2008 o 2008 R2? –

+0

+1 Esta es la ballena blanca de consultas – 8kb

+0

Originalmente en 2000 y estoy haciendo optimizaciones para 2005 – Cericme

Respuesta

2

Las expresiones de unión en SQL son constructivas, al igual que las expresiones aritméticas.

Es decir, se puede hacer lo siguiente:

A JOIN B ON <expr-AB> 

Pero también se puede sustituir por otra expresión de combinación para B:

A JOIN (B JOIN C ON <expr-BC>) ON <expr-AB> 

Y los parens pueden ser superfluos si el orden natural de precedencia daría el mismo resultado:

A JOIN B JOIN C ON <expr-BC> ON <expr-AB> 

Así que la gran consulta fugly que mostró es la sintaxis legal , pero ciertamente podría ser más claro.


veo la consulta como una jerarquía de esta manera:

so 
so --left--> stfl 
so --left--> stPres 
so --left--> o 
      o --inner-> bi 
         bi --inner-> selFac 
         bi --left--> p 
      o --left--> pp 
         pp --left--> pres 
         pp --left--> tblDuck 
         pp --left--> vwDuck 
      o --left--> pf 
         pf --left--> fl 
      o --left--> ops 

Me gustaría volver a escribir la consulta como la siguiente:

FROM tblStockChaos so 
LEFT OUTER JOIN tblWolveLocation stfl 
    ON so.WolveLocationId = stfl.WolveLocationId 
LEFT OUTER JOIN vwDonald stPres 
    ON so.DonaldId = stPres.DonaldId 
LEFT OUTER JOIN 
    (tblChaos o 
    INNER JOIN 
    (tblBillLeg bi 
     INNER JOIN @Facty selFac 
     ON bi.WolveId = selFac.WolveId 
     LEFT OUTER JOIN tblCheeseburger p 
     ON bi.CheeseburgerId = p.CheeseburgerId) 
    ON o.ChaosID = bi.ChaosId 
    LEFT OUTER JOIN 
    (tblDuckPez pp 
     LEFT OUTER JOIN vwDonald pres 
     ON pp.DonaldId = pres.DonaldId 
     LEFT OUTER JOIN tblDuck 
     ON pp.DuckID = tblDuck.DuckId 
     LEFT OUTER JOIN vwDuck 
     ON pp.DuckID = vwDuck.DuckId) 
    ON o.PezID = pp.PezID 
    LEFT OUTER JOIN tblPezFill 
    (tblPezFill pf 
     LEFT OUTER JOIN tblWolveLocation fl 
     ON pf.WolveLocationId = fl.WolveLocationId) 
    ON o.PezFillID = pf.PezFillID 
    LEFT OUTER JOIN tblChaosCheeseburgerShipped ops 
    ON o.ChaosID = ops.ChaosID 
) 

No puedo garantizar que tengo tiene todas las condiciones perfectas. Pero esa es la idea.

+0

Hubiera respondido de manera muy similar. – ErikE

2

Mi enfoque era generar un plan de consulta utilizando variables de tabla y luego intentar volver a escribir la consulta de la manera en que se compilaría.

Si configura con este código:

DECLARE @tblPezFill TABLE (PezFillID INT, WolveLocationID INT) -- pf/f1 
DECLARE @tblWolveLocation TABLE (WolveLocationID INT) -- stfl 
DECLARE @tblDuckPez TABLE (Pezid INT, DonaldID INT, DuckID INT) -- pp 
DECLARE @tblChaos TABLE (StockChaosID INT, ChaosID INT, PezID INT, 
    PezFillID INT) -- o 
DECLARE @tblBillLeg TABLE (WolveID INT, ChaosID INT, 
    CheeseburgerID INT) -- bi 
DECLARE @Facty TABLE (WolveId INT) -- selFac 
DECLARE @vwDonald TABLE (DonaldID INT) -- stPres 
DECLARE @tblStockChaos TABLE (StockChaosID INT, DonaldID INT, 
    WolveLocationID INT) -- so 
DECLARE @tblCheeseburger TABLE (CheeseburgerID INT) -- p 
DECLARE @tblChaosCheeseburgerShipped TABLE (ChaosID INT) -- ops 
DECLARE @tblDuck TABLE (DuckID INT) -- tblDuck 
DECLARE @vwDuck TABLE (DuckID INT) -- vwDuck 

Y a continuación, ejecute la consulta:

SELECT * 
FROM   @tblPezFill pf 
RIGHT OUTER JOIN @tblWolveLocation stfl 
RIGHT OUTER JOIN @tblDuckPez pp 
RIGHT OUTER JOIN @tblChaos o 
INNER JOIN @tblBillLeg bi 
INNER JOIN @Facty selFac 
ON bi.WolveId = selFac.WolveId 
ON o.ChaosID = bi.ChaosId 
LEFT OUTER JOIN @vwDonald stPres 
RIGHT OUTER JOIN @tblStockChaos so 
      ON stPres.DonaldId = so.DonaldId 
      ON o.StockChaosID = so.StockChaosID 
      ON pp.PezID = o.PezID 
      ON stfl.WolveLocationId = so.WolveLocationId 
      ON pf.PezFillID = o.PezFillID 
LEFT OUTER JOIN @tblCheeseburger p ON bi.CheeseburgerId = p.CheeseburgerId 
LEFT OUTER JOIN @tblChaosCheeseburgerShipped ops ON o.ChaosID = ops.ChaosID 
LEFT OUTER JOIN @vwDonald pres ON pp.DonaldId = pres.DonaldId 
LEFT OUTER JOIN @tblDuck tblDuck ON pp.DuckID = tblDuck.DuckId 
LEFT OUTER JOIN @vwDuck vwDuck ON pp.DuckID = vwDuck.DuckId 
LEFT OUTER JOIN @tblWolveLocation fl ON pf.WolveLocationId = fl.WolveLocationId 

El comienzo del plan de consulta se parece a esto:

alt text

El resto es solo una serie de uniones a la izquierda, así que las dejé fuera. Mi opinión es que si puedes duplicar el plan de consulta, sabrás que tu nueva consulta coincide exactamente con la lógica del original.

Esto es lo que ocurrió:

SELECT * 
FROM (
    SELECT 
    a2.WolveId, 
    a2.ChaosID, 
    a2.CheeseburgerID, 
    a2.PezFillID, 
    a2.PezID, 
    a2.StockChaosID, 
    a3.DonaldID, 
    a3.WolveLocationID 
    FROM ( 
    SELECT 
     selFac.WolveId, 
     a1.ChaosID, 
     a1.CheeseburgerID, 
     a1.PezFillID, 
     a1.PezID, 
     a1.StockChaosID 
    FROM @Facty selFac 
    INNER JOIN (
     SELECT 
     bi.ChaosID, 
     bi.CheeseburgerID, 
     bi.WolveID, 
     o.PezFillID, 
     o.PezID, 
     o.StockChaosID 
     FROM @tblBillLeg bi 
     INNER JOIN @tblChaos o 
     ON bi.ChaosID = o.ChaosID 
    ) a1 
     ON selFac.WolveId = a1.WolveID 
) a2 
    LEFT OUTER JOIN (
    SELECT 
     stPres.DonaldID, 
     so.StockChaosID, 
     so.WolveLocationID 
    FROM @vwDonald stPres 
    LEFT OUTER JOIN @tblStockChaos so 
     ON stPres.DonaldID = so.DonaldID 
) a3 
    ON a2.StockChaosID = a3.StockChaosID 
) a4 
LEFT OUTER JOIN @tblDuckPez pp 
    ON a4.PezID = pp.Pezid 
LEFT OUTER JOIN @tblCheeseburger p 
    ON a4.CheeseburgerID = p.CheeseburgerID 
LEFT OUTER JOIN @tblChaosCheeseburgerShipped ops 
    ON a4.ChaosID = ops.ChaosID 
LEFT OUTER JOIN @vwDonald pres 
    ON a4.DonaldID = pres.DonaldID 
LEFT OUTER JOIN @tblDuck tblDuck 
    ON pp.DuckID = tblDuck.DuckID 
LEFT OUTER JOIN @tblWolveLocation fl 
    ON a4.WolveLocationID = fl.WolveLocationID 

La única diferencia en mi plan de ejecución es que un par de campos tenían un paso adicional de compute scalar y que el conjunto final de exterior izquierdo se une no estaban en el exactamente el mismo orden que el original.

+0

No hubiera pensado en eso. – Cericme

Cuestiones relacionadas