LEFT JOIN(OUTER JOIN)与INNER JOIN的条件

时间:2015-06-22 10:01:37

标签: sql join left-join inner-join outer-join

SELECT A.COL1, B.COL1,C.COL1
FROM TABLEA A
LEFT JOIN TABLEB B ON A.COL1 = B.COL1
LEFT JOIN TABLEC C ON (
        C.COL3 IS NOT NULL
        AND (
              C.COL2 = 664
              AND A.COL1 = C.COL1
        )
)

关于SQL的技术性,LEFT JOIN TABLE C ON之后在括号中写的条件是什么意思?为什么那些必要?

3 个答案:

答案 0 :(得分:2)

内连接(JOIN或INNER JOIN,CROSS JOIN或逗号)首先执行CROSS JOIN。 (即返回可以通过从左表中追加一行并从右表中追加一行来生成的所有行。)然后任何ON都会删除不符合其条件的行。 OUTER JOIN为左表(LEFT)或右表(RIGHT)或两个表(FULL)返回相应的INNER JOIN plus 的行,任何用NULL扩展的不匹配行。 FROM a WHERE删除了不符合条件的行。

如果某个条件处于ON状态,则会在FROM中删除匹配的行。但是,如果该条件改为在WHERE中,那么匹配的行和通过后续连接合并它们的任何行仍然会被删除。因此,如果FROM只有内连接,那么条件是在ON还是在WHERE中并不重要。

但是如果FROM在一个条件上有OUTER JOIN,则删除不符合条件的交叉连接行,并添加某些NULL扩展行,而将该条件移动到WHERE则删除但不添加。

对于INNER JOIN而言,语言没有必要,因为而不是t1 INNER JOIN t2 ON condition而是(SELECT * FROM t1 INNER JOIN t2 WHERE condition)可能会涉及 var lst = new List<int>{1,2,3,4,4,5,6,7}; var lst2 = new List<int>{4,4,6}; int count=0; var hs= new HashSet<int>(lst2); //O(m) ... contains {4,6} foreach (var l in lst) // O(n) { if (hs.Contains(l)) // O(1) count++; } count.Dump(); //returns 3

从上面你可以得出以下结论:对于任何最后一次OUTER JOIN之后的一系列INNER JOINS(包括没有OUTER JOIN时),可以在它们的ON和WHERE之间自由移动条件。但不适用于任何最后一次OUTER JOIN之前或之前的ON,因为它们会影响其输入,从而影响输出的NULLed行。如果将这样的条件从ON移到WHERE,那么没有理由期望相同的结果。

对于您的代码:可能该查询旨在将A.COL1作为带有关联的A,B和C信息的ID返回,而不包含B信息的那些(包含B&amp; C信息NULL)和那些但没有但不具有C信息或者但不具有非NULL C.COL3或者但不具备C.COL2 = 664的人(包括C信息NULL) )。

答案 1 :(得分:0)

早期版本的ANSI SQL不包含连接条件的ON子句 - 它为所有内容使用了where子句。这对于内部联接很好,但是随着数据库应用程序开始使用外部联接,这种方法出现了问题。你们中的一些人可能还记得*==*的原始ANSI-89时代语法。这些用于谓词以定义外连接的行为。在这种情况下,除了从连接返回的普通行之外,我们还将保留A中不匹配的行:

SELECT A.COL1, B.COL1,C.COL1
FROM TABLEA A
LEFT JOIN TABLEB B ON A.COL1 = B.COL1
LEFT JOIN TABLEC C ON (
        C.COL3 IS NOT NULL
        AND (
              C.COL2 = 664
              AND A.COL1 = C.COL1
        )
)

当您试图弄清楚查询中应该发生什么时,这非常有用。它有助于在语义上定义应该从连接返回的行集。

  

ON子句:此语法允许您在两个表中指定连接键的列名   ON子句用于连接两个表中列名不匹配的表。连接条件将从WHERE子句中的过滤条件中删除。

答案 2 :(得分:0)

OUTER JOIN C NULL可能A.COL1.,因为C.COL2 = 664无法匹配

如果是这种情况,则永远不会有WHERE意味着任何ON语句都会丢弃该行。

通过将条件放入JOIN子句,您要求将其应用于Q_in = input ('Please enter the rate of magma flow into dike in [m^3s^-1]: '); t_flow_days = input ('Please enter the amount of time magma is flowing into the dike in [days]: '); t_flow_seconds = t_flow_days * 24 * 3600; % Flow time converted to seconds % This sums a number of planes to simulate the volume of the dyke as a % function of time. V_Dike_t = (Q_in.*t_flow_seconds); % V in the ellipsoid at t pi = 3.14159265359; % Value of pi c_axis_d = 2000; % ellipsoidal axis "c" (m) b_axis_d = 250; % ellipsoidal axis "b" (m) a_axis = (3*V_Dike_t)/(4*pi*b_axis_d*c_axis_d) % a-axis fxn of volume (m) a_axis_d = a_axis; % a-axis fxn of V (m) nSlices = 1e6; % defines the # of intervals or contours verticalStep = c_axis_d./nSlices; largerRadiusStep = b_axis_d./nSlices; smallerRadiusStep = a_axis_d./nSlices; sliceLargerRadius = b_axis_d; sliceSmallerRadius = a_axis_d; V_of_Half_ellipsoid = 0; for sliceIndex = 1:nSlices sliceArea = pi * sliceLargerRadius * sliceSmallerRadius; sliceVolume = sliceArea * verticalStep; sliceLargerRadius = sliceLargerRadius - largerRadiusStep; sliceSmallerRadius = sliceSmallerRadius - smallerRadiusStep; V_of_Half_ellipsoid = V_of_Half_ellipsoid + sliceVolume; end finalVolume = V_of_Half_ellipsoid*2; finalVolume_km = finalVolume * 0.000000001; V_flow_km3 = V_Dike_t*0.000000001 V_dyke_km3 = finalVolume_km 条件,而不是作为结果的过滤器。

对于非外连接,没有区别。