请帮助将Tsql“隐式连接”转换为显式连接

时间:2010-07-30 20:19:30

标签: tsql refactoring performance left-join inner-join

抱歉,我几乎是一个SQL菜鸟。这必须在MSFT SQL,Oracle和Sybase中运行。在以下代码段中,我需要将inner join上的IJKL之间的IJ.PO_id = KL.PO_id更改为left join上的IJ.PO_id = KL.PO_id。所以,我相信我必须重新考虑这一点。好吧,隐式连接不是最易读的,至少在我的同事看来。我想我会同意,直到我发展自己的品味。对不起,为了以防万一,我修改了表格和字段名称。

/* @IJ_id is an input stored proc patrameter. */
from AB, 
     CD,
     EF,
     GH,
     IJ,
     KL
where
    EF.EF_id = IJ.EF_id and
    IJ.EF_id = AB.EF_id and
    EF.ZY_id = IJ.ZY_id and
    IJ.ZY_id = AB.ZY_id and
    IJ.IJ_id = AB.IJ_id and
    IJ.IJ_id = @IJ_id and
    EF.XW_id = GH.GH_id and
    AB.VU_code = CD.VU_code and
    IJ.TS > 0 and
    IJ.RQ = 0 and
    EF.RQ = 0 and
    AB.RQ = 0 and
    IJ.PO_id = KL.PO_id;

现在,我的困难在于where子句中有很多事情发生。看起来不像a.b = c.d的东西将保留在where子句中,但并非所有看起来像a.b = c.d的东西都很容易转换为显式连接。困难的部分是,理想情况是邻居之间的条件 - AB+CDCD+EFEF+GHGH+IJIJ+KL但他们现在不是那么有组织。我可以重新订购一些,但最终我不想忘记我的目标:我希望新查询不会慢,我希望新查询的可读性不低。看起来我可能会更好地攻击我需要改变的部分,而且大部分都是一样的。我不确定我是否可以这样做。

如果您理解我的意图,请建议更好的查询。如果你没有,那么请告诉我如何改进这个问题。感谢。

3 个答案:

答案 0 :(得分:3)

我认为它应该是这样的:

FROM AB
JOIN CD ON AB.VU_code = CD.VU_code
JOIN IJ ON IJ.EF_id = AB.EF_id AND IJ.ZY_id = AB.ZY_id AND IJ.IJ_id = AB.IJ_id
JOIN EF ON EF.EF_id = IJ.EF_id AND EF.ZY_id = IJ.ZY_id
JOIN GH ON EF.XW_id = GH.GH_id
JOIN KL ON IJ.PO_id = KL.PO_id
WHERE
    IJ.IJ_id = @IJ_id AND
    IJ.TS > 0 AND
    IJ.RQ = 0 AND
    EF.RQ = 0 AND
    AB.RQ = 0

我试图安排表格,以便遵守以下规则:

  • 每个连接条件都会提到它在一侧加入的新表。
  • 如果该表尚未加入,则在连接条件中未提及任何表。
  • 其中一个操作数是常量的条件保留为WHERE条件。

最后一条规则很难 - 不可能从你的错位名称中判断一个条件是否应该是一个连接的一部分或者是where子句的一部分。两者都会为INNER JOIN提供相同的结果。条件是连接的一部分还是where子句的一部分取决于表之间关系的语义。

您需要根据具体情况考虑每个条件:

  • 它是否定义了两个表之间的关系?把它放在JOIN中。
  • 是结果的过滤器吗?将它放在WHERE子句中。

一些指导原则:

  • 包含来自用户的参数的条件不太可能是应该移动到连接的内容。
  • 在加入条件下通常不会发现不等式。

答案 1 :(得分:1)

它可能不会比你给出的例子更具可读性......

from AB a
join CD c on a.VU_Code = c.VU_Code
join EF e on a.EF_id = e.EF_id and e.RQ = 0
join GH g on e.XW_id = g.GH_id
join IJ i on a.IJ_id = i.IJ_id and e.EF_id = i.EF_id
         and a.EF_id = i.EF_id and e.ZY_id = i.ZY_id
         and a.ZY_id = i.ZY_id and i.TS > 0 and i.RQ = 0
LEFT join KL k on i.PO_id = k.PO_id
where 
    i.IJ_id = @IJ_id and 
    a.RQ = 0

答案 2 :(得分:1)

使用:

 FROM AB t1
 JOIN CD t2 ON t2.VU_code = t1.VU_code
 JOIN GH t4 ON t4.gh_id = t3.xw_id
 JOIN IJ t5 ON t5.ZY_id = t1.ZY_id
           AND t5.IJ_id = t1.IJ_id
           AND t5.EF_id = t1.EF_id 
           AND t5.IJ_id = @IJ_id 
           AND t5.TS > 0 
           AND t5.RQ = 0 
 JOIN EF t3 ON t3.ef_id = t5.ef_id
           AND t3.zy_id = t5.zy_id
           AND t3.RQ = 0
 JOIN KL t6 ON t6.po_id = t5.po_id -- Add LEFT before JOIN for LEFT JOIN
WHERE ab.qu = 0

它们在原始ANSI-89语法的序列中存在别名,但由于别名引用而调整了顺序 - 在定义之前无法引用表别名。

这是ANSI-92 JOIN语法 - 没有性能优势,但它确实意味着OUTER连接语法是一致的。只需在“JOIN KL ...”之前添加 LEFT 即可将其转换为LEFT JOIN。