MySQL (select_paren) union_order_or_limit 行为

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: MySQL语法 (select_paren) union_order_or_limt行为

MySQL (select_paren) union_order_or_limit 行为

MySQL源码版本5.6.2

MySQL Syntax(sql_yacc.yy)

select:
      select_init

select_init:
    SELECT_SYM select_init2
    | '(' select_paren ')' union_opt
 ;
union_opt:
    /* Empty */ { $$= 0; }
      | union_list { $$= 1; }
      | union_order_or_limit { $$= 1; }
  ;
union_order_or_limit:
    order_or_limit:

order_or_limit:
    order_clause opt_limit_clause_init
    | limit_clause

limit_clause:
    LIMIT limit_options

处理逻辑

LIMIT

limit_options以limit_option ',' limit_option为例

      | limit_option ',' limit_option
      {
        SELECT_LEX *sel= Select;//Select表示current_select
        sel->select_limit= $3;
        sel->offset_limit= $1;
        sel->explicit_limit= 1;
      }

由该逻辑可以看出:

(select * from t1 [order by x | limit num]) limit off_x, count_y;//current_select不变

相当于

select * from t1 [order by x] limit off_x, count_y;

Order by

order_clause:
      ORDER_SYM BY
      {
        LEX *lex=Lex;
        SELECT_LEX *sel= lex->current_select;
        SELECT_LEX_UNIT *unit= sel-> master_unit();
        if (sel->linkage != GLOBAL_OPTIONS_TYPE &&
            sel->olap != UNSPECIFIED_OLAP_TYPE &&
            (sel->linkage != UNION_TYPE || sel->braces))
        {
          my_error(ER_WRONG_USAGE, MYF(0),
                   "CUBE/ROLLUP", "ORDER BY");
          MYSQL_YYABORT;
        }
        if (lex->sql_command != SQLCOM_ALTER_TABLE && !unit->fake_select_lex)
        {
          /*
            A query of the of the form (SELECT ...) ORDER BY order_list is
            executed in the same way as the query
            SELECT ... ORDER BY order_list
            unless the SELECT construct contains ORDER BY or LIMIT clauses.
            Otherwise we create a fake SELECT_LEX if it has not been created
            yet.
          */
          SELECT_LEX *first_sl= unit->first_select();
          if (!unit->is_union() &&
              (first_sl->order_list.elements ||
               first_sl->select_limit) &&
              unit->add_fake_select_lex(lex->thd))
            MYSQL_YYABORT;
        }
      }
      order_list
    ;

从上面可以看出当select_paren中没有order和limit的时候,current_select不会改变,有以下等价方式:

(select no_order_or_limit) order by xx [limit x];

等价于

select no_order_or_limit order by xx limit x;

当存在order或者limit的时候,MySQL会创建GLOBAL_OPTIONS_TYPE的fake_select_lex,这个fake_select_lex作为OPTIONS存在。

同时将current_select指向fake_select_lex。

  fake_select_lex->linkage= GLOBAL_OPTIONS_TYPE;
  if (!is_union())
  {
    /* 
      This works only for 
      (SELECT ... ORDER BY list [LIMIT n]) ORDER BY order_list [LIMIT m],
      (SELECT ... LIMIT n) ORDER BY order_list [LIMIT m]
      just before the parser starts processing order_list
    */ 
    global_parameters= fake_select_lex;
    fake_select_lex->no_table_names_allowed= 1;
    thd_arg->lex->current_select= fake_select_lex;
  }

因此当select_paren中存在order或者limit的时候,curren_select会指向fake_select,添加order by[limit]。我们可以认为其等价方式是:

(select xxx  order by xx limit x) order by yy[limit y];

等价于

select * from (select xxx order by xx limit x) ta order by yy limit y;

实验结果


mysql> create table t1(c1 int primary key);

mysql> insert into t1 values(1), (2),(3), (4),(5);

//limit option测试   
mysql> (select * from t1 limit 1) limit 5;
+----+
| c1 |
+----+
|  1 |
|  2 |
|  3 |
|  4 |
|  5 |
+----+
 //等价:select * from t1 limit 5;

mysql> (select * from t1 order by c1 desc limit 1) limit 4;
+----+
| c1 |
+----+
|  5 |
|  4 |
|  3 |
|  2 |
+----+
//等价:select * from t1 order by c1 desc limit 4;

//order by[limit] option测试
mysql> (select * from t1) order by c1 desc limit 2;
+----+
| c1 |
+----+
|  5 |
|  4 |
+----+
//等价:select * from t1 order by c1 desc limit 2;

mysql> create table t(c1 int);

mysql> insert into t values(1), (1), (2), (2);

mysql> (select * from t group by(c1)) order by c1 limit 3;
+------+
| c1   |
+------+
|1 |
|2 |
+------+
//等价于select * from t group by (c1) order by c1 limit 3;

mysql> (select * from t1 limit 3) order by c1 desc limit 1;
+----+
| c1 |
+----+
|  3 |
+----+

//等价于:select * from (select * from t1 limit 3) ta order by c1 desc limit 1;

mysql> (select * from t1 order by c1 desc limit 2) order by c1;
+----+
| c1 |
+----+
|  4 |
|  5 |
+----+
//等价于:select * from (select * from t1 order by c1 desc limit 2) ta order by c1;

mysql> (select * from t1 order by c1 desc limit 2) order by c1 limit 1;
+----+
| c1 |
+----+
|  4 |
+----+   
//等价于:select * from (select * from t1 order by c1 desc limit 2) ta order by c1 limit 1;

mysql> insert into t values(3, 3);
mysql> (select * from t group by (c1) order by c1 desc limit 2) order by c1 limit 1;
+------+
| c1   |
+------+
|2 |
+------+
//等价于: select * from (select * from t group by (c1) order by c1 desc limit 2) ta order by c1 limit 1;

总结

MySQL语法 (select_paren) union_order_or_limt等价方式如下:

1、limit as option

(select xxx) limit yy;

等价于:

select xxx_no_limit limit yy;

2、order by [limit] as option

2.1、select_paren without order or limit

(select no_order_or_limit) order by yyy [limit y];

等价于:

select no_order_or_limit order by yyy [limit y];

2.2、select_paren with order or limit

(select xxx [order by xx | limit x]) order by yyy [limit y];

等价于:

select * from (select xxx [order by xx | limit x]) ta order by yyy [limit y];
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
2月前
|
监控 关系型数据库 MySQL
PHP与MySQL的结合:实现局域网上网行为监控软件的数据库管理
在当今信息化时代,网络安全日益成为重要的话题。为了有效监控和管理局域网上网行为,开发一个基于PHP和MySQL的数据库管理系统是一个理想的选择。本文将介绍如何结合PHP和MySQL,开发一款简单而高效的局域网上网行为监控软件,并重点关注数据库管理方面的实现。
191 0
|
4月前
|
Oracle 关系型数据库 MySQL
oceanbase在MySQL语法兼容模式下,在授权语法、行为方面 是否与 开源MySQL完全一致 ?
oceanbase在MySQL语法兼容模式下,在授权语法、行为方面 是否与 开源MySQL完全一致 ?
102 2
|
关系型数据库 MySQL
MySQL基础-删除/更新行为
添加了外键之后,再删除父表数据时产生的约束行为,我们就称为删除/更新行为。具体的删除/更新行为有以下几种:
155 0
|
SQL 存储 JSON
MySQL分割一行为多行的思路
MySQL分割一行为多行的思路
|
存储 SQL JSON
MySQL Case-通过optimizer_trace看MySQL优化器行为
我们在日常维护数据库的时候,如果遇到慢语句查询的时候,我们一般会怎么做?执行EXPLAIN去查看它的执行计划?是的。我们经常会这么做,然后看到执行计划展示给我们的一些信息,告诉我们MySQL是如何执行语句的。但是,执行计划往往只给我们带来了最基础的分析信息,比如是否有使用索引,还有一些其他供我们分析的信息,比如使用了临时表、排序等等。
385 0
|
SQL Oracle 关系型数据库
Oracle/Mysql迁移到Postgresql事务回滚行为差异(开发避坑系列)
Mysql或Oracle迁移到Postgresql系产品后,经常会发生事务回滚导致的问题,具体问题一般都是类似于: **为什么我没rollback,我的事务就自己回滚了?** 下面我举一个简单的例子,说明下PG和其他两款DB在事务回滚行为上的差异 ## Oracle事务内报错后的行为 (完整代码贴在文章最后) ```java Class.fo
909 0
|
关系型数据库 MySQL 数据库管理
MySQL 修改表默认字符集行为
修改表默认字符集的行为,只是针对新加的字段的在没有指定字符集的时候,给该字段确定字符集。老的字段还是原先的字符集,因此在使用中会出现表的字符集明明是utf8mb4的,但是确存不了emoji。因此,推荐不用要这种方式修改表的默认字符集
1568 0
|
15天前
|
关系型数据库 MySQL 数据库
mysql卸载、下载、安装(window版本)
mysql卸载、下载、安装(window版本)
|
1月前
|
关系型数据库 MySQL 数据库
rds安装数据库客户端工具
安装阿里云RDS的数据库客户端涉及在本地安装对应类型(如MySQL、PostgreSQL)的客户端工具。对于MySQL,可选择MySQL Command-Line Client或图形化工具如Navicat,安装后输入RDS实例的连接参数进行连接。对于PostgreSQL,可以使用`psql`命令行工具或图形化客户端如PgAdmin。首先从阿里云控制台获取连接信息,然后按照官方文档安装客户端,最后配置客户端连接以确保遵循安全指引。
82 1
|
4天前
|
关系型数据库 MySQL 数据库
《MySQL 简易速速上手小册》第1章:MySQL 基础和安装(2024 最新版)
《MySQL 简易速速上手小册》第1章:MySQL 基础和安装(2024 最新版)
25 4