MYSQL:不能/如何使用子查询作为完全限定的CTE

问题描述 投票:2回答:1

我想执行以下操作。这在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));
mysql sql postgresql subquery common-table-expression
1个回答
2
投票

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_queryFROM子句中对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中做到这一点。

使用INNOT 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关键字?

© www.soinside.com 2019 - 2024. All rights reserved.