在同一个查询中使用左连接和内连接

Posted

技术标签:

【中文标题】在同一个查询中使用左连接和内连接【英文标题】:Using left join and inner join in the same query 【发布时间】:2012-03-29 22:16:22 【问题描述】:

以下是我使用左联接的查询,该查询按预期工作。我想要做的是进一步添加另一个表过滤这个查询,但这样做有问题。我将把这个新表称为table_3 并想添加table_3.rwykey = runways_updatable.rwykey 的位置。任何帮助将不胜感激。

SELECT * 
FROM RUNWAYS_UPDATABLE 
LEFT JOIN TURN_UPDATABLE 
ON RUNWAYS_UPDATABLE.RWYKEY = TURN_UPDATABLE.RWYKEY 
WHERE RUNWAYS_UPDATABLE.ICAO = 'ICAO'
AND (RUNWAYS_UPDATABLE.TORA > 4000 OR LDA > 0) 
AND (TURN_UPDATABLE.AIRLINE_CODE IS NULL OR TURN_UPDATABLE.AIRLINE_CODE = '' 
OR TURN_UPDATABLE.AIRLINE_CODE = '') 

'*************编辑澄清********** ******* 这是我想使用的另一个内部连接语句,我想将这两个语句结合起来。

SELECT * 
FROM RUNWAYS_UPDATABLE A, RUNWAYS_TABLE B
WHERE A.RWYKEY = B.RWYKEY

'***到目前为止我的建议如下,但出现语法错误

     SELECT RUNWAYS_UPDATABLE.*, TURN_UPDATABLE.*,  AIRPORT_RUNWAYS_SELECTED.* 
     FROM RUNWAYS_UPDATABLE
       INNER JOIN  AIRPORT_RUNWAYS_SELECTED 
          ON RUNWAYS_UPDATABLE.RWYKEY = AIRPORT_RUNWAYS_SELECTED.RWYKEY
     LEFT JOIN TURN_UPDATABLE
          ON RUNWAYS_UPDATABLE.RWYKEY = TURN_UPDATABLE.RWYKEY 

注意:如果我注释掉内连接并保留左连接,反之亦然,它可以工作,但是当我在查询中有两个连接时,那就是我收到语法错误的时候。

【问题讨论】:

你能告诉我们有什么问题吗?您收到什么以及您期望什么? 【参考方案1】:

在搜索如何使LEFT JOIN 依赖于另一个INNER JOIN 时,我总是遇到这个问题。这是我在搜索“在同一查询中使用 LEFT JOININNER JOIN”时搜索的示例:

SELECT *
FROM foo f1
LEFT JOIN (bar b1
  INNER JOIN baz b2 ON b2.id = b1.baz_id
) ON
  b1.id = f1.bar_id

在本例中,b1 仅在也找到 b2 时才会包含在内。

【讨论】:

有趣的语法 哇,从来不知道!! 感激不尽;坐了最后 2 小时,正要重构代码时遇到了巧妙的左/内连接技巧 - 靶心!【参考方案2】:

请记住,在左连接中过滤右侧表应该在连接本身中完成。

select *
from table1 
  left join table2
    on table1.FK_table2 = table2.id
    and table2.class = 'HIGH'

【讨论】:

澄清一下,你也可以去:where table2.class= 'HIGH' OR table2.class is null; @robertking 不,返回的行数可能不同,因为table2.class 首先可能包含空值。 Join 条件会将它们过滤掉,而 where 条件将包括它们。此外,如果使用连接条件,则将返回 table1 中的所有行,其中条件将排除 table1 中在 table2 中没有对应行的行,其中class is null or class = 'HIGH'【参考方案3】:

我终于明白了。谢谢大家的帮助!!!

SELECT * FROM 
(AIRPORT_RUNWAYS_SELECTED 
 INNER JOIN RUNWAYS_UPDATABLE 
 ON AIRPORT_RUNWAYS_SELECTED.RWYKEY = RUNWAYS_UPDATABLE.RWYKEY) 
LEFT JOIN TURN_UPDATABLE ON RUNWAYS_UPDATABLE.RWYKEY = TURN_UPDATABLE.RWYKEY

【讨论】:

【参考方案4】:

LEFT JOIN 之前添加您的INNER_JOIN

  SELECT * 
  FROM runways_updatable ru
    INNER JOIN table_3 t3 ON ru.rwykey = t3.rwykey
    LEFT JOIN turn_updatable tu
      ON ru.rwykey = tu.rwykey
      AND (tu.airline_code IS NULL OR tu.airline_code = '' OR tu.airline_code = '')
  WHERE ru.icao = 'ICAO'
    AND (ru.tora > 4000 OR ru.lda > 0)

如果您在INNER JOIN 之前先LEFT JOIN,那么如果turn_updatable 中没有匹配的行,您将无法从table_3 获得结果。这可能是您想要的,但由于您的table_3 的连接条件仅引用runways_updatable,我会假设您想要来自table_3 的结果,即使turn_updatable 中没有匹配的行。

编辑

正如@NikolaMarkovinović 指出的那样,您应该在连接条件本身中过滤您的LEFT JOIN,如上所示。否则,如果右侧表 (turn_updatable) 中不满足该条件,您将无法从左侧表 (runways_updatable) 中获得结果。


编辑 2:OP 提到这实际上是 Access,而不是 mysql

在 Access 中,可能是表别名不同。试试这个:

  SELECT [ru].*, [tu].*, [ars].*
  FROM [runways_updatable] AS [ru]
    INNER JOIN [airport_runways_selected] AS [ars] ON [ru].rwykey = [ars].rwykey
    LEFT JOIN [turn_updatable] AS [tu]
      ON [ru].rwykey = [tu].rwykey
      AND ([tu].airline_code IS NULL OR [tu].airline_code = '' OR [tu].airline_code = '')
  WHERE [ru].icao = 'ICAO'
    AND ([ru].tora > 4000 OR [ru].lda > 0)

【讨论】:

感谢您尝试回答此问题,但您的回答无效。我收到一个语法错误说明:查询表达式中缺少运算符。我所做的是将 table_3 替换为 table_3 并收到该错误 @Will:你用的是什么版本的 MySQL?我在此处发布的任何答案中都没有看到任何语法错误。 @Will:访问不是 MySQL。但是,根据Access 2003 doc,应该可以使用相同的语法。您使用的是哪个版本的 Access? Access 2003,我已经对我原来的问题进行了编辑,以显示我到目前为止的内容,但我仍然遇到语法错误 @Will:我对 MySQL 和 Access 之间的区别不是很熟悉,但请查看我对这个答案的最新更新,看看它是否有效。【参考方案5】:

如果它只是您要添加的内部联接,请执行此操作。您可以在同一查询中添加任意数量的联接。不过,如果这不是您想要的,请更新您的答案

  SELECT * 
  FROM RUNWAYS_UPDATABLE 
  LEFT JOIN TURN_UPDATABLE 
  ON RUNWAYS_UPDATABLE.RWYKEY = TURN_UPDATABLE.RWYKEY 
  INNER JOIN table_3
  ON table_3.rwykey = runways_updatable.rwykey
  WHERE RUNWAYS_UPDATABLE.ICAO = 'ICAO'
  AND (RUNWAYS_UPDATABLE.TORA > 4000 OR LDA > 0) 
  AND (TURN_UPDATABLE.AIRLINE_CODE IS NULL OR TURN_UPDATABLE.AIRLINE_CODE = '' 
  OR TURN_UPDATABLE.AIRLINE_CODE = '') 

【讨论】:

感谢您尝试回答此问题,但您的回答无效。我收到一个语法错误说明:查询表达式中缺少运算符。 既然您说这是访问权限,我敢打赌这来自您设置中的其他内容。您可以尝试直接运行上述查询(如所写..没有访问逻辑),还是您正在尝试这样做?【参考方案6】:

我不太确定你想要什么。但也许是这样的:

SELECT RUNWAYS_UPDATABLE.*, TURN_UPDATABLE.*
FROM RUNWAYS_UPDATABLE
JOIN table_3 
    ON table_3.rwykey = runways_updatable.rwykey
LEFT JOIN TURN_UPDATABLE 
ON RUNWAYS_UPDATABLE.RWYKEY = TURN_UPDATABLE.RWYKEY 
WHERE RUNWAYS_UPDATABLE.ICAO = 'ICAO'
AND (RUNWAYS_UPDATABLE.TORA > 4000 OR LDA > 0) 
AND (TURN_UPDATABLE.AIRLINE_CODE IS NULL OR TURN_UPDATABLE.AIRLINE_CODE = '' 
OR TURN_UPDATABLE.AIRLINE_CODE = '') 

【讨论】:

感谢您尝试回答我的问题,但我收到一条错误消息:FROM 子句中的语法错误 尝试将SELECT *更改为SELECT RUNWAYS_UPDATABLE.*, TURN_UPDATABLE.* - 错误可能是table_3上重复的列名引起的。 好消息。更新了答案 试过了,但仍然出现语法错误会更新我所拥有的。我取出了一些代码以使其不那么复杂。【参考方案7】:

对于 Postgres,查询规划器不保证连接的执行顺序。为了保证可以使用@Gajus 解决方案,但是如果内部连接表的列存在 Where 条件,则会出现问题。要么需要在相应的 Join 条件中仔细添加 where 子句,否则最好使用子查询内部连接部分,然后左连接输出。

【讨论】:

以上是关于在同一个查询中使用左连接和内连接的主要内容,如果未能解决你的问题,请参考以下文章

结合左外连接和内连接 + 聚合函数 - 空结果集问题

左连接和内连接组

ms-access 中的左连接和内连接

MySQL连接查询 内连接和外连接的区别

sql子查询和连接查询的区别是啥呢?

SQL内连接与外连接用法与区别