文章
· 十月 29, 2021 阅读大约需 5 分钟

第六十章 SQL命令 JOIN(二)

第六十章 SQL命令 JOIN(二)

单向外部联接

IRIS支持单向外部联接:左外部联接和右外部联接。

使用标准的“inner”联接时,当一个表的行链接到第二个表的行时,第一个表中找不到第二个表中对应行的行将从输出表中排除。

使用单向外联接时,即使第二个表中没有匹配项,第一个表中的所有行也会包括在输出表中。使用单向外连接,第一个表会从第二个表中取出相关信息,但不会因为第二个表中缺少匹配项而牺牲自己的行。

例如,如果查询首先列出Table1并创建一个左外部联接,那么它应该能够看到Table1中的所有行,即使它们在Table2中没有对应的记录。

在指定单向外联接时,在FROM子句中命名表的顺序非常重要。对于左外部联接,指定的第一个表是联接的源表。对于右外部联接,指定的第二个表是联接的源表。因此,%INORDER%STARTTABLE优化关键字不能与RIGHT OUTER JOIN一起使用。以下语法相互矛盾,导致SQLCODE-34错误:FROM%INORDER TABLE1 RIGHT OUTER JOIN TABLE2 ON....

外部联接语法

IRIS支持两种表示外连接的格式:

  1. ANSI标准语法:LEFT OUTER JOINRIGHT OUTER JOIN。SQL标准语法将外联接放在SELECT语句的FROM子句中,而不是WHERE子句中,如下例所示:
FROM tbl1 LEFT OUTER JOIN tbl2 ON (tbl1.key = tbl2.key) 
  1. ODBC规范外部联接扩展语法,使用转义语法{OJ Join-Expression},其中Join-Expression是任何ANSI标准联接语法。

Null填充

单向外联接执行空值填充。这意味着,如果源表的某一行的合并列具有空值,则会为非源表中的相应字段返回空值。

左外部联接条件由以下语法表示:

A LEFT OUTER JOIN B ON A.x=B.y

这指定返回A中的每一行。对于返回的每个A行,如果有一个B行使得A.x=B.Y,则还将返回所有相应的B值。

如果没有A.x=B.yB行,则填充空值会导致该A行的所有B值返回为空值。

例如,考虑包含患者信息的Patient表,其中包括一个字段Patient
指定患者主治医生的DocIDID代码。
数据库中的一些患者没有主诊医生,因此对这些患者记录“患者”。
DocID字段为NULL
现在,我们在Patient表和Doctor表之间执行连接,以生成一个包含患者姓名和相应医生姓名的表。

SELECT Patient.PName,Doctor.DName
   FROM Patient INNER JOIN Doctor
   ON Patient.DocID=Doctor.DocID

INNER JOIN不执行空填充。
因此,如果没有相应的医生姓名,则不会返回患者姓名。

单向外联接确实执行空值填充。因此,没有相应医生名称的患者名称将为Doctor.DName返回NULL

SELECT Patient.PName,Doctor.DName
   FROM Patient LEFT OUTER JOIN Doctor
   ON Patient.DocID=Doctor.DocID

单向外联接条件(包括必要的空值填充)在其他条件之前应用。因此,WHERE子句中不能由填充空值的值满足的条件(例如,B中字段的范围或相等条件)有效地将AB的单向外联接转换为常规联接(内联接)。

例如,如果将子句“WHERE Doctor.Age < 45”添加到上面的两个“Patient”表查询中,则它们是等效的。但是,如果添加子句“WHERE Doctor.Age < 45 OR Doctor.Age is null”,它将保留这两个查询之间的差异。

混合外部和内部连接

IRIS支持任意顺序的混合内部连接和外部连接的所有语法。

多重连接和隐式连接的性能

默认情况下,查询优化器将多个连接操作按其对最优序列的最佳估计排序。
这不一定是在查询中指定的连接顺序。
可以在FROM子句中指定%INORDER%FIRSTTABLE%STARTTABLE查询优化选项,以显式指定表连接的顺序。

查询优化器可以执行子查询扁平化,将某些子查询转换为显式连接。
当子查询数量较少时,这将极大地提高连接性能。
当子查询的数量超过一个或两个时,子查询扁平化在某些情况下可能会略微降低性能。
可以在FROM子句中指定%NOFLATTEN查询优化选项,以显式指定不应该执行子查询扁平化。

只有当子查询扁平化后,查询中的连接总数不超过15个连接时,查询优化器才会执行子查询扁平化。
指定超过15个联接,如果其中一些联接是隐式联接或联接子查询,则会导致查询性能的显著下降。

示例

下面的示例显示了在表1和表2上执行JOIN操作的结果。

Table1

Column1 Column2
aaa bbb
ccc ccc
xxx yyy
hhh zzz

Table2

Column1 Column3
ggg hhh
xxx zzz

CROSS JOIN 示例

SELECT * FROM Table1 CROSS JOIN Table2
Column1 Column2 Column1 Column3
aaa bbb ggg hhh
aaa bbb xxx zzz
ccc ccc ggg hhh
ccc ccc xxx zzz
xxx yyy ggg hhh
xxx yyy xxx zzz
hhh zzz ggg hhh
hhh zzz xxx zzz

NATURAL JOIN 示例

SELECT * FROM Table1 NATURAL JOIN Table2
Column1 Column2 Column1 Column3
xxx yyy xxx zzz

请注意,NATURAL JOIN的 IRIS实现不会合并具有相同名称的列。

使用ON子句的INNER JOIN示例

SELECT * FROM Table1 INNER JOIN Table2
     ON Table1.Column1=Table2.Column3
Column1 Column2 Column1 Column3
hhh zzz ggg hhh

使用USING子句的INNER JOIN示例

SELECT * FROM Table1 INNER JOIN Table2
  USING (Column1)
Column1 Column2 Column1 Column3
xxx yyy xxx zzz

注意,USING子句的IRIS实现不会合并具有相同名称的列。

LEFT OUTER JOIN 示例

SELECT * FROM Table1 LEFT OUTER JOIN Table2
  ON Table1.Column1=Table2.Column3
Column1 Column2 Column1 Column3
aaa bbb null null
ccc ccc null null
xxx yyy null null
hhh zzz ggg hhh

RIGHT OUTER JOIN 示例

SELECT * FROM Table1 RIGHT OUTER JOIN Table2
     ON Table1.Column1=Table2.Column3
Column1 Column2 Column1 Column3
hhh zzz ggg hhh
null null xxx zzz

FULL OUTER JOIN

SELECT * FROM Table1 FULL OUTER JOIN Table2
  ON Table1.Column1=Table2.Column3
Column1 Column2 Column1 Column3
aaa bbb null null
ccc ccc null null
xxx yyy null null
hhh zzz ggg hhh
null null xxx zzz
讨论 (0)1
登录或注册以继续