Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 混合左连接和右连接?为什么?_Sql_Join - Fatal编程技术网

Sql 混合左连接和右连接?为什么?

Sql 混合左连接和右连接?为什么?,sql,join,Sql,Join,在项目中发现的一些遗留代码中进行重构。这是针对MSSQL的。问题是,我不明白为什么我们使用混合的左连接和右连接,并将一些连接条件整理在一起 我的问题是:这不是在某些地方创建隐式内部联接,在其他地方创建隐式完全联接吗 我所属的学校,几乎任何东西都可以用左(和内部/完整)或右(和内部/完整)来写,但那是因为我喜欢在可能的情况下保持简单 顺便说一句,我们将所有这些东西都转换为在oracle数据库上工作,所以也许有一些优化规则在Ora上的工作方式不同 例如,下面是其中一个查询的一部分:

在项目中发现的一些遗留代码中进行重构。这是针对MSSQL的。问题是,我不明白为什么我们使用混合的左连接和右连接,并将一些连接条件整理在一起

我的问题是:这不是在某些地方创建隐式内部联接,在其他地方创建隐式完全联接吗

我所属的学校,几乎任何东西都可以用左(和内部/完整)或右(和内部/完整)来写,但那是因为我喜欢在可能的情况下保持简单

顺便说一句,我们将所有这些东西都转换为在oracle数据库上工作,所以也许有一些优化规则在Ora上的工作方式不同

例如,下面是其中一个查询的一部分:

        FROM    Table1
        RIGHT OUTER JOIN Table2
            ON Table1.T2FK = Table2.T2PK
        LEFT OUTER JOIN Table3
        RIGHT OUTER JOIN Table4
        LEFT OUTER JOIN Table5
            ON Table4.T3FK = Table5.T3FK
               AND Table4.T2FK = Table5.T2FK
        LEFT OUTER JOIN Table6
        RIGHT OUTER JOIN Table7
            ON Table6.T6PK = Table7.T6FK
        LEFT OUTER JOIN Table8
        RIGHT OUTER JOIN Table9
            ON Table8.T8PK= Table9.T8FK
            ON Table7.T9FK= Table9.T9PK
            ON Table4.T7FK= Table7.T7PK
            ON Table3.T3PK= Table4.T3PK
        RIGHT OUTER JOIN ( SELECT   *
                           FROM     TableA
                           WHERE    ( TableA.PK = @PK )
                                    AND ( TableA.Date BETWEEN @StartDate
                                                                    AND     @EndDate )
                         ) Table10
            ON Table4.T4PK= Table10.T4FK
            ON Table2.T2PK = Table4.T2PK

这里我可能遗漏了一些东西,但左连接和右连接之间的唯一区别是源表的写入顺序,因此具有多个左连接或多个右连接与混合没有什么区别。与混合使用相比,使用所有左/右都可以轻松地实现与完全外接的等效,这很可能被转换为使用所有左连接:我将查看并移动每个右中的右表,使其位于所有现有左表之上,然后您可以将每个右连接转换为左连接。我不确定您是否会在幕后获得任何完整连接——如果查询看起来像这样,那么这可能是此特定查询的一个怪癖,而不是SQL Server“规则”:您提供的查询似乎以一种相当混乱的方式将其混在一起

至于Oracle的优化--这当然是可能的。我本人没有Oracle方面的经验,但与一位熟悉这一领域的朋友交谈时,Oracle(不知道是什么版本)对谓词的顺序非常挑剔。例如,使用SQL Server,您可以编写自己的way子句,这样列可以按任何顺序排列,并且可以使用索引,但使用Oracle,您最终必须按列在索引中的显示顺序指定列,以便使用索引获得最佳性能。如前所述——不知道较新的甲骨文是否如此,但较旧的甲骨文确实如此(显然)


我不能说这是否解释了这种特殊的结构。如果经过多年的修改,它可能不是一个理想的代码,而清理正是它所需要的。

我要做的一件事是,在处理这个问题之前,确保您知道您期望的结果。不想“修复”它并返回不同的结果。尽管老实说,对于一个设计糟糕的查询,我不确定您现在是否得到了正确的结果

对我来说,这看起来像是有人随着时间的推移所做的事情,可能最初是从内部联接开始,意识到它们不起作用,然后改为外部联接,但不想麻烦更改查询中引用表的顺序


出于维护目的,我特别关心的是将ON子句放在您要连接的表旁边,并将所有连接转换为左连接,而不是混合右连接和左连接。将表4和表3的ON子句放在表9旁边对我来说毫无意义,并且会导致对查询实际返回内容的混淆。您可能还需要更改联接的顺序,以便转换为所有左联接。就我个人而言,我更喜欢从其他人将加入的主表(看起来是表2)开始,然后从那里沿着食物链往下走。

在同一个查询中,我们有一些
左外连接
s和
右外连接
s。通常,这样的查询很大,已经存在很长时间,可能一开始写得很糟糕,而且很少得到维护。我假设引入了
右外部联接
s作为维护查询的一种手段,而不必承担重构查询时不可避免的风险

我认为大多数SQL编码人员最容易使用all
LEFT-OUTER-JOIN
s,这可能是因为
FROM
子句是用英语从左到右读取的

我唯一一次使用
右外部联接
是在基于现有查询编写新查询时(无需重新发明轮子),我需要将
内部联接
更改为
外部联接
。与其在
FROM
子句中更改
连接的顺序,只是为了能够使用
左外部连接
,我宁愿使用
右外部连接
,这不会打扰我。但这是相当罕见的。如果原始查询有
左外部连接
s,那么我最终会得到
左外部连接
-和
右外部连接
的混合,这同样不会困扰我。但我还没遇到过


请注意,对于不支持
完全外部联接的SQL产品(如Access数据库引擎),一种解决方法是在同一查询中联合
左外部联接
右外部联接。

左外部联接和
右外部联接是纯语法糖

任何
左连接
都可以通过切换集合转换为
右连接

早在
9i
Oracle
使用此结构:

WHERE  table1.col(+) = table2.col
(+)
此处表示可为空的列,
LEFT
RIGHT
连接可以通过简单的切换来模拟:

WHERE  table1.col = table2.col(+)
MySQL
中,没有
完全外部连接,需要对其进行仿真

通常是这样做的:

SELECT  *
FROM    table1
LEFT JOIN
        table2
ON      table1.col = table2.col
UNION ALL
SELECT  *
FROM    table1
RIGHT JOIN
        table2
ON      table1.col = table2.col
WHERE   table1.col IS NULL
,并且复制
连接
并将
左侧
替换为
右侧
,比交换表更方便

请注意,在
SQL Server
计划中,
Hash Left-Semi-Join
Hash Right-Semi-Join
是不同的运算符

对于这样的查询:

SELECT  *
FROM    table1
WHERE   table1.col IN
        (
        SELECT  col
        FROM    table2
        )