所有包含EXISTS子查询和ON的LEFT JOIN的MySQL SELECT查询的问题,其中ON引用了外部SELECT

时间:2019-11-09 07:38:00

标签: mysql mariadb left-join

这是问题所在。在运行该类型的任何查询

SELECT field1
FROM table1
WHERE EXISTS (SELECT table2.field2, table3.field3, table3.field4
              FROM table2 LEFT JOIN table3 ON table3.field3 = table2.field2 
                                           AND table3.field4 = table1.field1
              WHERE "some condition");

我收到此错误:

Unknown column 'table1.field1' in 'on clause'

另一方面,此查询

SELECT field1
FROM table1
WHERE EXISTS (SELECT table2.field2, table3.field3, table3.field4
              FROM table2 LEFT JOIN table3 ON table3.field3 = table2.field2 
              WHERE "some condition"
                AND table3.field4 = table1.field1);

工作正常。

可能有其他选择,例如,它可以是内部联接而不是外部联接,否定子查询检查(不存在),其中不需要子句且字段列表可以不同。唯一关键的部分是EXISTS子查询,并在JOIN处于ON条件下引用table1.field1。

我在多个MySQL和MariaDB服务器上尝试了相同的结果!还尝试在线上找到完全相同问题,因此在SO上没有成功。

根据其中一条评论中的建议,我用一个真实的例子修改了这个问题。

表格:

CREATE TABLE `sessions` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `user_id` int(11) DEFAULT NULL,
    `browser` varchar(255) DEFAULT NULL,
    PRIMARY KEY (`id`)
)

CREATE TABLE `browsers` (               
    `id` int(11) NOT NULL DEFAULT '0',
    `browser` varchar(255) DEFAULT NULL
)

要获取使用所有浏览器的所有用户,我运行此查询

select distinct user_id
from sessions as t1
where not exists (select t2.id, browsers.id
                  from sessions as t2 LEFT JOIN browsers ON t2.browser = browsers.browser 
                                                         AND t2.user_id = t1.user_id
                  where browsers.id IS NULL);

我收到的错误消息:

Error Code : 1054
Unknown column 't1.user_id' in 'on clause'

当然,我需要的输出是选择带有用户列表的查询结果集。

我知道如何重写此特定任务的查询,因此这不是问题。问题在于,使用此模式运行查询可以执行任何其他任务,因为它看起来非常合乎逻辑并且是很好的SQL。

我的问题是我在做错什么,如果那是一个错误,我如何避免保持相同的查询结构。

1 个答案:

答案 0 :(得分:1)

我认为您遇到了bug#96946,MySQL在JOIN ON子句中不允许外部引用。

如果我没记错的话,这是对双重嵌套的NOT EXISTS查询的重写,我认为该语句实际上将在MySQL中被接受:

SELECT DISTINCT user_id
FROM sessions AS s1
WHERE NOT EXISTS (SELECT *
                  FROM browsers AS b
                  WHERE NOT EXISTS (SELECT *
                                    FROM sessions s2
                                    WHERE s1.user_id = s2.user_id AND
                                          s2.browser = b.browser
                                   )
                 );