请帮助转换Tsql“;隐式联接;变成明确的

请帮助转换Tsql“;隐式联接;变成明确的,tsql,refactoring,performance,left-join,inner-join,Tsql,Refactoring,Performance,Left Join,Inner Join,对不起,我几乎是个SQL noob。这必须适用于MSFT SQL、Oracle以及Sybase。在下面的代码片段中,我需要将IJ和KL之间的内部连接在IJ.PO\u id=KL.PO\u id上更改为左连接也在IJ.PO\u id=KL.PO\u id上。因此,我认为我必须重新考虑这一点。嗯,隐式连接不是最可读的,至少在我的同事眼中是这样。我想我会同意的,直到我发展出自己的品味。对不起,为了以防万一,我弄坏了表名和字段名 /* @IJ_id is an input stored proc pat

对不起,我几乎是个SQL noob。这必须适用于MSFT SQL、Oracle以及Sybase。在下面的代码片段中,我需要将
IJ
KL
之间的
内部连接
IJ.PO\u id=KL.PO\u id
上更改为
左连接
也在
IJ.PO\u id=KL.PO\u 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+CD
CD+EF
EF+GH
GH+IJ
IJ+KL
,但它们现在没有组织起来。我可以重新排序一些,但最终我不想忘记我的目标:我希望新查询不会变慢,我希望新查询的可读性不会降低。似乎我最好只修改我需要修改的部分,而基本上保持不变。我不确定我是否能做到


如果你理解我的意图,请提出一个更好的问题。如果你没有,那么请告诉我如何改进这个问题。谢谢。

我想应该是这样的:

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条件
最后一条规则是一条困难的规则——不可能从你被弄乱的名字中分辨出一个条件应该是join的一部分还是where子句的一部分。对于内部联接,两者都将给出相同的结果。条件应该是join的一部分还是where子句的一部分取决于表之间关系的语义

你需要根据每种情况考虑每种情况:

  • 它是否定义了两个表之间的关系?把它放在接头上
  • 这是对结果的过滤吗?把它放在WHERE子句中
一些准则:

  • 包含用户参数的条件不太可能是应该移动到联接的条件
  • 不等式通常不存在于连接条件中

它的可读性不可能比您给出的示例差

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
使用:

它们按照原始ANSI-89语法的顺序使用别名,但顺序因别名引用而调整-在定义表别名之前无法引用它


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

按照当前的编写方式,这些都是内部联接,您正在重写为显式内部联接,以便可以更改为LEFT JOIN?您是对的。我只想将其中一个更改为左连接,
IJ+KL:IJ.PO_id=KL.PO_id
。因此,我认为将所有其他连接重写为显式内部连接将A)使我的更改成为可能,B)使其更具可读性。很高兴看到您正在重写此内容,因为t-sql在任何使用隐式连接的版本中都无法正确处理左连接。这是隐式连接更难维护的完美示例@HLGEM,我想无知和不知道那会是什么样子会有好处:)“它的可读性不可能比你给出的例子差。”。。。“你把我的话都说出来了。哈哈,你几乎写了一些不太可读的东西。不太好,试试Netherless:PBtw,其中一个应该是左连接。t1、t2等是别名吗?如果是这样,我不确定我是否希望在生产代码中使用它们。再次抱歉,我不想透露真名。只是好奇-你用t1。。。t6帮助你达成这个目标?@Hamish Grubijan:我正在更新你的评论,以解决左派加入问题。请参阅更新。表别名是您的选择-根据您的意愿使用。从其他示例中,我可以看到确实有些条件可以是join或where子句的一部分。我天真的理解是,如果我帮助查询优化器尽早消除尽可能多的事情,我会帮助它完成它的工作。此查询是“严重”存储过程的一部分,该存储过程对一些较大的表(几百到几千条记录)进行操作。在这种情况下,如果我必须在可读性和性能之间做出选择,那么我会选择性能。75%的用户将在MSFT SQL上运行,20%的用户将在oracle上运行,5%的用户将在Sybase上运行(如果有)helps@HamishGrubijan:在何处或在何处选择不是一个性能问题——性能应该是相同的。当您将其更改为LEFT JOIN时,您将得到不同的结果,这取决于JOIN中是否有常量条件,或者作为where子句的一部分。我想我不能给你一条永远有效的规则。您需要根据具体情况确定哪一个连接到何处。@Hamish Grubijan:当使用ANSI-92连接语法时,在where和JOIN中设置条件确实会影响返回的结果。连接中的条件(即:IJ.RQ=0)是在连接表之前运行的。标记,因此作为练习,我开始填写Excel表格,以帮助我确保翻译符合犹太规范,但这很快让我发明了一种符号。我的下一个想法是写一个Python脚本,然后让我思考——有人说
 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