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

标签 mysql sql postgresql subquery common-table-expression

我想执行以下操作。这在 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 8.0 引入了对公共(public)表表达式 (CTE) 的支持,即早期版本的 MySQL 不支持的“WITH”。

https://dev.mysql.com/doc/refman/8.0/en/with.html


编辑

是的,我们可以为内联 View (或者 MySQL 中的派生表)分配一个别名,并在查询中的其他地方引用该别名。在此示例中,my_query 是我们分配给内联 View 的别名。

 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

语法实际上是有效的。但是IN(子查询)FROM子句中对my_query的引用不是也不可能是对表别名的引用外部查询。这是不允许的。

因此,我们预计查询可能会抛出一个有关子查询中的 my_query 引用的错误,该错误是未解析的标识符“未知表”,诸如此类。

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

CREATE TABLE my_query (val INT PRIMARY KEY);
INSERT INTO my_query (val) VALUES (7);

然后重新运行查询,该引用 my_query 现在将解析为该表。 (不是查询中分配的别名。)

公共(public)表表达式 (CTE) 在解决此类问题方面向前迈出了重要一步,能够在多个不允许的位置引用内联 View 。

如果问题是“如何在 MySQL 中模拟通用表表达式 (CTE) 功能”,则 google 搜索会导致此问题:

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

原创


您是指CTE(公共(public)表表达式,即WITH 子句)而不是CMT 吗?

如果您指的是 CMT,我很抱歉,因为在这个问题的上下文中,尚不清楚该缩写词代表什么。也许这意味着集中管理表,但我不明白这有什么关系。

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


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

使用具有 INNOT IN 的子查询(SELECT)是有效的。这些都是有效的:

    foo IN ( subquery )

    foo NOT IN ( subquery )

NOT IN(子查询) 的一个大“陷阱”是子查询返回 NULL 值。如果列表中存在 NULL 值,NOT IN 的计算结果为 NULL,这意味着它无法对任何行计算结果为 TRUE。作为演示,请考虑:

 SELECT 3 NOT IN (2,NULL,4)

也许这可以回答所提出的问题。

我们只是猜测所问的问题是什么。 (有人问问题吗?)

“不起作用”是什么意思?查询返回意外结果? MySQL 返回错误?查询执行了很长时间并且出现“挂起”?我们只是猜测“不起作用”的含义。


为什么我们在连接操作中使用老式的逗号运算符语法,而不是(我们仍然可以调用它吗?较新的)JOIN 关键字?

关于MYSQL:不能/如何使用子查询作为完全限定的 CTE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49931341/

相关文章:

mysql - 更新 SQL 中的完整记录?

sql - 获取最近 10 个日期的行

java - 返回已连接完整实体的选定属性

sql - 如何限制第 1 列条目在第 2 列(postgresql)中有重复条目?

php - OS X Lion Apache 和 PHP 无法通信

php - Laravel 7:MariaDB与Redis结合使用,但是Redis在大型对象上的运行速度较慢

php - 如何通过已从 mysql/phpmyadmin 导出为 mydatabase.sql 的 php/pdo 连接到 sql 数据库?

mysql - 在 MySql 中存储 html 语法

java - JPA 查询中的 sql 查询构建器?

php MySQL语法错误