在同一个查询中使用左连接和内连接
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 JOIN
和 INNER 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 子句,否则最好使用子查询内部连接部分,然后左连接输出。
【讨论】:
以上是关于在同一个查询中使用左连接和内连接的主要内容,如果未能解决你的问题,请参考以下文章