博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MySQL (select_paren) union_order_or_limit 行为
阅读量:6871 次
发布时间:2019-06-26

本文共 5034 字,大约阅读时间需要 16 分钟。

MySQL (select_paren) union_order_or_limit 行为

MySQL源码版本5.6.2

MySQL Syntax(sql_yacc.yy)

select:      select_initselect_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_clauselimit_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];

转载地址:http://hxvfl.baihongyu.com/

你可能感兴趣的文章
“C语言” 读书札记(四)之[再续编译执行]
查看>>
[CODE] Dahua Lin贡献的两个开源软件
查看>>
高斯消元法求解线性方程组的解集
查看>>
C++ 沉思录——Chap5:代理类
查看>>
通向架构师的道路(第一天)之Apache整合Tomcat - lifetragedy的专栏 - 博客频道 - CSDN.NET...
查看>>
DD-WRT v24-sp2的WDS中继设置
查看>>
SQL语句中ALTER的用法
查看>>
最近读的javascript,一些文章
查看>>
SVN服务器搭建和使用(三)
查看>>
JSON入门指南--客户端处理JSON
查看>>
Objective-C内存布局
查看>>
qsort的另类玩法,无聊写着耍耍
查看>>
每日一乐,健康多滋味~~
查看>>
[Oracle] - Connect to a PDB of Oracle12c
查看>>
VS2015 android 设计器不能可视化问题解决。
查看>>
移动数据统计平台分析
查看>>
httppp 1.4.0 发布,HTTP响应时间监控
查看>>
ASP.NET MVC加载ASCX之后,并为之赋值
查看>>
使用SDWebImage淡入淡出的方式加载图片
查看>>
nmon与nmonanalyser系统性能分析
查看>>