【问题标题】:Can anyone fathom a why do this or how it works correctly with this bit of SQL?任何人都可以理解为什么这样做或它如何与这段 SQL 一起正常工作?
【发布时间】:2010-09-02 21:29:16
【问题描述】:

我已经更改了表名,但是我在一个我正在优化的 SP 中发现了这个 FROM 语句,我想知道它是如何产生的,你为什么会做这样的事情,为什么它仍然存在工作。

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

我已经把它清理干净了

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

我认为应该是等价的,我需要一些测试数据。我只是不明白第一个版本是如何工作的。

【问题讨论】:

标签: sql sql-server tsql


【解决方案1】:

SQL 中的连接表达式是建设性的,就像算术表达式一样。

也就是说,您可以执行以下操作:

A JOIN B ON <expr-AB>

但你也可以用另一个连接表达式代替 B:

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

如果自然优先顺序会给出相同的结果,那么括号可能是多余的:

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

所以你展示的巨大的丑陋的查询是合法的语法,但它肯定可以更清楚。


我将查询视为这样的层次结构:

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

我会这样重写查询:

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
  )

我不能保证我已经满足了所有条件。但这就是想法。

【讨论】:

  • 我的回答会非常相似。
【解决方案2】:

我的方法是使用表变量生成查询计划,然后尝试以编译方式重写查询。

如果您使用此代码进行设置:

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

然后运行查询:

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

查询计划的开头是这样的:

剩下的只是一系列左连接,所以我把它们排除在外。我的想法是,如果您可以复制查询计划,您就会知道您的新查询与原始查询完全匹配。

这是我想出的:

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

我的执行计划中唯一的区别是几个字段有一个额外的步骤compute scalar,并且最后一组左外连接的顺序与原来的顺序不同。

【讨论】:

  • 我不会想到的。
猜你喜欢
  • 1970-01-01
  • 2022-01-11
  • 2013-08-26
  • 2016-09-19
  • 1970-01-01
  • 2016-06-16
  • 1970-01-01
  • 1970-01-01
  • 2022-06-16
相关资源
最近更新 更多