【问题标题】:MySQL "WITH" clauseMySQL "WITH" 子句
【发布时间】:2010-09-24 09:46:16
【问题描述】:

我正在尝试使用 MySQL 创建带有“WITH”子句的视图

WITH authorRating(aname, rating) AS
   SELECT aname, AVG(quantity)
   FROM book
   GROUP BY aname

但似乎 MySQL 不支持这个。

我认为这是非常标准的,我确信 Oracle 支持这一点。无论如何强制MySQL使用“WITH”子句?我已经尝试过使用 MyISAM 和 innoDB 引擎。这两个都不行。

【问题讨论】:

    标签: mysql sql common-table-expression


    【解决方案1】:

    更新:MySQL 8.0 终于有了通用表表达式的功能,包括递归 CTE。

    这是一个宣布它的博客:http://mysqlserverteam.com/mysql-8-0-labs-recursive-common-table-expressions-in-mysql-ctes/

    以下是我早先的回答,最初是我在 2008 年写的。


    MySQL 5.x 不支持使用 SQL-99 中定义的WITH 语法进行查询,也称为通用表表达式。

    这是自 2006 年 1 月以来对 MySQL 的功能请求:http://bugs.mysql.com/bug.php?id=16244

    其他支持公用表表达式的 RDBMS 产品:

    【讨论】:

    • SQLite 支持 WITH clause,截至 2014 年 2 月 3 日发布的 version 3.8.3
    • 我将 H2 和 Firebird 添加到列表中。
    • @BillKarwin:我不相信 MySQL 会实现 任何 现代 DBMS 功能(检查约束、窗口函数、表达式索引、部分索引、延迟约束...... )。
    • @a_horse_with_no_name,他们似乎更重视可扩展性。长期以来,他们一直专注于提高内部结构的可扩展性,以利用现代硬件。但我认为他们忽略了 SQL 特性。
    • @BlakeMcBride,你错了,你的评论是 FUD,没有事实依据。 Oracle 还拥有其他数据库产品,这些产品可以做 Oracle DB 做得不好的事情。示例:TimesTen、BerkeleyDB。他们收购了这些数据库以扩大市场。 MySQL 在 Web 应用市场占据主导地位,而 Oracle DB 不是,所以他们收购了 MySQL。对于甲骨文来说,束缚 MySQL 是没有意义的。我在 4 月份的会议上与 Oracle MySQL 开发人员进行了交谈,他们实际上正在为 MySQL 实施 WITH。
    【解决方案2】:

    您可能对以下内容感兴趣:

    select * from (
        select * from table
    ) as Subquery
    

    【讨论】:

    • 你能解释一下子查询吗?我可以选择 * from ( (select * from table1) UNION ALL (select * from table2) ) 分组吗?
    • @Kathy 嗨,Subquery 是我用于派生表本身的名称。当您使用from ( ... ) 时,您会创建类似于临时表(派生表)的东西,并且它需要一个名称。这就是我使用as Subquery 的原因。回答您的问题,是的,您可以,但您必须为外部派生表命名(就在Group By 之前)。希望对您有所帮助。
    • @MostyMostacho 你好,可以在这里喂我一点吗?我正在努力将其转换为 MySQL。你能看看吗? link 或者在这里回答我的问题? link
    【解决方案3】:

    你的语法正确:

    WITH AuthorRating(AuthorName, AuthorRating) AS
       SELECT aname         AS AuthorName,
              AVG(quantity) AS AuthorRating
       FROM Book
       GROUP By Book.aname
    

    但是,正如其他人所提到的,MySQL 不支持此命令。在 SQL:1999 中添加了 WITH; SQL 标准的最新版本是 SQL:2008。您可以在Wikipedia 上找到有关支持 SQL:1999 各种功能的数据库的更多信息。

    传统上,MySQL 在支持 SQL 标准方面稍有滞后,而诸如 Oracle、SQL Server(最近)和 DB2 等商业数据库则更紧跟它们的步伐。 PostgreSQL 通常也非常符合标准。

    您可能想查看 MySQL 的路线图;我不完全确定何时支持此功能,但它非常适合创建可读的汇总查询。

    【讨论】:

      【解决方案4】:

      Oracle 确实支持 WITH。

      看起来像这样。

      WITH emps as (SELECT * FROM Employees)
      SELECT * FROM emps WHERE ID < 20
      UNION ALL
      SELECT * FROM emps where Sex = 'F'
      

      @ysth WITH 很难用谷歌搜索,因为它是一个通常被排除在搜索之外的常用词。

      您需要查看SELECT docs 以了解子查询分解的工作原理。

      我知道这并没有回答 OP,但我正在清理任何可能已经开始的混乱。

      【讨论】:

      • 无论如何也没有解决我的困惑。你是说没有 WITH 子句但有 WITH 语句?
      • 啊,我明白了。它是选择之前的选择子句。它也可以在 CREATE VIEW 中使用吗?与加入子选择有何不同?我没有在网上看到 WITH 后的名称有参数的示例 - 这些是如何工作的?
      • 这是非常不同的。请注意,相同的 subqry 被使用了两次,而不必定义它两次。当然,您可以在其中复制/粘贴相同的查询,但这是一个简单的示例。想象一下,如果 WITH 子句在一个页面上继续,并且在主查询中被使用了 4 次。到时候你会很感激的。
      • 我链接到文档,应该解释语法。就一个观点而言。当然它在那里工作。
      【解决方案5】:

      基于@Mosty Mostacho 的回答,对于确定哪些条目不存在于表中且不存在于任何其他数据库中的特定情况,您可以在 MySQL 中执行相同的操作。

      select col1 from (
         select 'value1' as col1 union
         select 'value2' as col1 union
         select 'value3' as col1
      ) as subquery
      left join mytable as mytable.mycol = col1
      where mytable.mycol is null
      order by col1
      

      您可能希望使用具有宏功能的文本编辑器将值列表转换为带引号的 select union 子句。

      【讨论】:

        【解决方案6】:

        MariaDB 现在支持 WITH。 MySQL 现在不是。 https://mariadb.com/kb/en/mariadb/with/

        【讨论】:

          【解决方案7】:

          你试过临时表吗? 这解决了我的问题:

          create temporary table abc (
          column1 varchar(255)
          column2 decimal
          );
          insert into abc
          select ...
          or otherwise
          insert into abc
          values ('text', 5.5), ('text2', 0815.8);
          

          然后你可以在这个会话的每一个选择中使用这个表:

          select * from abc inner join users on ...;
          

          【讨论】:

          【解决方案8】:
             WITH authorRating as (select aname, rating from book)
             SELECT aname, AVG(quantity)
             FROM authorRating
             GROUP BY aname
          

          【讨论】:

            猜你喜欢
            • 2010-11-16
            • 2019-07-29
            • 2010-12-26
            • 2021-02-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-11-25
            相关资源
            最近更新 更多