MySQL“ WITH”子句


98

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

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

但是MySQL似乎并不支持这一点。

我认为这是非常标准的,并且我确定Oracle支持此标准。无论如何,有没有强制MySQL使用“ WITH”子句?我已经尝试过使用MyISAM和innoDB引擎。这两个都不起作用。

Answers:


109

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

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

以下是我最初在2008年写的答案。


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

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

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


1
SQLite支持的WITH子句3.8.3版本在2014年2月3日发布。
Martijn 2014年

我将H2和Firebird添加到列表中。
a_horse_with_no_name 2014年

2
@BillKarwin:我相信MySQL不会实现任何现代DBMS功能(检查约束,窗口函数,表达式索引,部分索引,延迟约束...)。
a_horse_with_no_name 2014年

2
@a_horse_with_no_name,它们似乎在可伸缩性上具有更高的优先级。他们长期以来一直致力于使内部结构更具可扩展性,以利用现代硬件。但是我认为他们忽略了SQL功能。
比尔·卡温

1
@BlakeMcBride,您错了,您的评论是FUD,实际上没有任何依据。Oracle还拥有其他数据库产品,这些产品执行Oracle DB不能很好完成的工作。例如:TimesTen,BerkeleyDB。他们收购了这些数据库以扩大市场。MySQL在Web应用程序市场中占主导地位,而Oracle DB没有,因此他们收购了MySQL。Oracle对MySQL施加束缚是没有意义的。我在四月份的会议上与Oracle MySQL开发人员进行了交谈,实际上他们正在着手为MySQL实现WITH。
Bill Karwin

17

您可能对这样的东西感兴趣:

select * from (
    select * from table
) as Subquery

你能解释一下子查询吗?我可以从*中选择*((从table1中选择*)从UNION ALL(从table2中选择*))分组吗?

1
@Kathy Hi,Subquery是我用于派生表本身的名称。使用时,from ( ... )您需要创建一个类似临时表(派生表)的文件,并且需要一个名称。这就是我使用的原因as Subquery。回答您的问题,可以,但是您必须在外部派生表中放置一个名称(位于之前Group By)。希望能有所帮助。
Mosty Mostacho 2012年

@MostyMostacho您好,请在这里给我一点汤匙吗?我正在努力将其转换为MySQL。你可以看看吗?在这里链接或回答我的问题?链接
Pranav 2015年

13

您的语法正确:

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的路线图;我不确定何时可以支持此功能,但是对于创建可读的汇总查询非常有用。


9

Oracle确实支持WITH。

看起来像这样。

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

@ysth WITH很难在Google上搜索,因为它是通常不包含在搜索中的常用词。

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

我知道这不能解决操作问题,但我正在清理可能已经开始的混乱情况。


无论如何都没有消除我的困惑。您是否在说没有WITH子句,但是有WITH语句?
ysth

1
知道了 这是选择之前的选择子句。也可以在CREATE VIEW中使用它吗?与加入子查询有何不同?我在网上看不到示例,其中WITH后面的名称带有参数-这些参数如何工作?
ysth

1
完全不同。请注意,同一子查询被使用两次,而不必定义两次。当然,您可以在其中复制/粘贴相同的查询,但这是一个简单的示例。想象一下,如果WITH子句继续出现在页面上,并且在主查询中被使用了4次。那你会很感激的。

我链接到文档,应该解释语法。据认为。当然可以。


2

在@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子句。


1
   WITH authorRating as (select aname, rating from book)
   SELECT aname, AVG(quantity)
   FROM authorRating
   GROUP BY aname

0

您是否尝试过临时表?这解决了我的困惑:

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 ...;

1
我必须注意:stackoverflow.com/questions/343402/…您不能两次打开表:-(
克劳斯

我对表中小数据集的解决方案:创建表abc2(如abc);插入abc2中,从abc中选择*;
克劳斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.