我想执行以下操作。这在MySQL中是非法的。 PostGRESQL中的相关CTE(“with”子句)工作正常。这里的假设是MySQL中的子查询不是完全合格的CTE。
请注意:这个查询显然非常愚蠢,它已被消毒和缩短,以便您的观看乐趣和简洁地突出问题。
请注意,“获得对称差异”任务与手头的问题正交。
SELECT A.val
FROM
(SELECT val FROM tableA) AS A,
(SELECT val FROM tableB) AS B
WHERE (A.val NOT IN (SELECT val FROM B)
OR B.val NOT IN (SELECT val FROM A));
PostGRES的例子(坦率地没有经过测试,因为我目前还没有PostGRES数据库进行测试,但我100%肯定它会起作用...我过去做过类似的事情):
WITH A as (SELECT val FROM tableA),
B as (SELECT val from tableB)
SELECT A.val FROM A, B
WHERE (A.val NOT IN (SELECT val FROM B)
OR B.val NOT IN (SELECT val FROM A));
UPDATE
MySQL 8.0引入了对公用表表达式(CTE)的支持,即早期版本的MySQL不支持的“WITH”。
https://dev.mysql.com/doc/refman/8.0/en/with.html
编辑
是的,我们可以为内联视图(或MySQL派生表中的派生表)分配别名,并在查询中的别处引用别名。在此示例中,my_query
是我们分配给内联视图的别名。
SELECT my_query.val
FROM ( SELECT val FROM foo ) my_query
WHERE my_query.val
ORDER
BY my_query.val
但是我们不能在子查询的FROM子句中引用该别名。例如,在此构造中:
SELECT my_query.val
FROM ( SELECT val FROM foo ) my_query
WHERE 7 IN ( SELECT val FROM my_query )
ORDER
BY my_query.val
语法实际上是有效的。但是在my_query
的FROM
子句中对IN (subquery)
的引用不是也不能引用外部查询中的表别名。这是不允许的。
所以我们希望查询可能会在子查询中引发一个关于my_query
引用的错误,该子查询是未解析的标识符“unknown table”,类似的东西。
请注意,我们可以创建一个名为my_query
的表,例如
CREATE TABLE my_query (val INT PRIMARY KEY);
INSERT INTO my_query (val) VALUES (7);
然后重新运行查询,该引用my_query
现在将解析为该表。 (不是查询中指定的别名。)
公共表表达式(CTE)在解决此类问题方面向前迈出了重要一步,即在多个地方引用内联视图的能力,否则不允许这样做。
如果问题是“如何在MySQL中模拟公用表表达式(CTE)功能”,谷歌搜索会在SO上引出这个问题:
How do you use the "WITH" clause in MySQL?
原版的
你的意思是CTE(Common Table Expression,即WITH子句)而不是CMT?
如果你的意思是CMT,我道歉,因为在这个问题的背景下,不清楚这个首字母缩略词代表什么。也许它意味着中央管理表,但我不知道这是如何相关的。
如果您在询问MySQL是否支持公用表表达式(CTE),那么答案是否定的。或者,至少,还没有。
从发布的SQL示例中,似乎不需要CTE或内联视图甚至子查询。也许SQL已经过度简化,以至于不清楚查询应该实现什么。 (它不应该得到对称的差异,所以我们不打算提出明显的替代方案,如何在MySQL中做到这一点。
使用IN
和NOT IN
的子查询(SELECT)是有效的。这些都是有效的:
foo IN ( subquery )
foo NOT IN ( subquery )
使用NOT IN (subquery)
的一个重要的“问题”是子查询返回NULL值。如果列表中包含NULL值,则NOT IN
的计算结果为NULL,这意味着对于任何行,它都不能求值为TRUE。作为演示,请考虑:
SELECT 3 NOT IN (2,NULL,4)
也许这回答了被问到的问题。
我们只是在猜测被问到的问题。 (有问题吗?)
什么是“不工作”?查询返回意外结果? MySQL正在返回错误?查询执行很长时间并且似乎“挂起”?我们只是猜测什么不工作意味着什么。
为什么我们使用旧式逗号运算符语法进行连接操作,而不是(我们甚至可以称之为?更新)JOIN
关键字?