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

时间:2018-04-19 22:48:20

标签: mysql sql postgresql subquery common-table-expression

我想执行以下操作。 MySQL中的 IS ILLEGAL 。 PostGRESQL中的相关CTE(“with”子句) DOES WORK 。这里的假设是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));

1 个答案:

答案 0 :(得分:2)

<强>更新

MySQL 8.0引入了对公用表格表达式(CTE)的支持,即&#39; WITH&#39;哪个早期版本的MySQL不支持。

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的{​​{1}}子句中对FROM的引用不是也不能引用外部查询中的表别名。这是不允许的。

因此,我们希望查询可能会在子查询中引发一个关于IN (subquery)引用的错误,该子查询是未解析的标识符&#34; unknown table&#34;,等等。

请注意,我们可以创建一个名为my_query的表,例如

my_query

然后重新运行查询,引用CREATE TABLE my_query (val INT PRIMARY KEY); INSERT INTO my_query (val) VALUES (7); 现在将解析为该表。 (不是查询中指定的别名。)

公用表格表达式(CTE)在解决此类问题方面向前迈出了重要一步,能够在多个地方引用内联视图,否则不允许这样做。

如果问题是,&#34;如何在MySQL&#34;中模拟公用表表达式(CTE)功能,谷歌搜索会在SO上引出这个问题:

How do you use the "WITH" clause in MySQL?

<强>原始

你的意思是 CTE (公用表格式,即WITH子句)而不是CMT?

如果你的意思是CMT,我道歉,因为在这个问题的背景下,它不清楚这个首字母缩略词代表什么。也许这意味着集中管理表,但我不知道这是如何相关的。

如果您在询问MySQL是否支持公用表表达式(CTE),那么答案是否定的。或者,至少,还没有。

从发布的SQL示例中,似乎不需要CTE或内联视图甚至子查询。也许SQL已经过度简化,以至于它不清楚查询应该实现什么。 (它不应该得到对称差异,所以我们不会建议明显的替代方案,如何在MySQL中做到这一点。

使用带有my_queryIN的子查询(SELECT)是有效的。这些都是有效的:

NOT IN

一个大的&#34;陷阱&#34; with foo IN ( subquery ) foo NOT IN ( subquery ) 是子查询返回NULL值的时间。如果列表中有NULL值,NOT IN (subquery)的计算结果为NULL,这意味着它不能为任何行计算为TRUE。作为演示,请考虑:

NOT IN

也许这回答了被问到的问题。

我们只是在猜测被问到的问题。 (有问题吗?)

是什么意思&#34;不工作&#34; ?查询返回意外结果? MySQL正在返回错误?查询执行时间很长,看起来像是&#34;挂起&#34;?我们只是猜测哪些不起作用。

为什么我们使用旧式逗号运算符语法进行连接操作,而不是(我们甚至可以称之为更新) SELECT 3 NOT IN (2,NULL,4) 关键字?