KES数据库SELECT语句

本文详细介绍了SQLSELECT语句的核心部分,包括DISTINCT、目标属性、FROM子句(表连接)、WHERE子句、GROUPBY子句、HAVING子句和ORDERBY子句的处理机制,以帮助理解SQL查询语句的构建和执行过程。
摘要由CSDN通过智能技术生成

1 概述

simple-select是一条SELECT语句的最核心部分,从simple-select的语法定义可以看出,它由如下子句组成:去除行重复的DISTINCT (标识符opt-distinct)、目标属性(标识符target-list)、 SELECT INTO子句(标识符into-clause)、FROM子句(标识符from-clause)、 WHERE子句(标识符where_clause) 、 CROUP BY子句(标识符group-clause)、HAVING子句(标识符having-clause)和窗口子句(标识符window-clause)。在成功匹配simple-select语法结构后,将创建一个SelectStmt结构体,并将各子句赋值到结构体中相应的字段。
此外, simple-select还可以定义为其他的形式(见文件Gram. y),如VALUES子句、关系表达式以及多个SELECT语句的交并差等,但这些情况最终都会转化成最基本的simple_select形式来处理。而对于simple-select来说,目标属性(标识符target list)、FROM子句(标识符from-clause)、 WHERE子句(标识符where-clause)以及GROUP BY子句(标识符groupclause)是最重要的部分,下面将结合一个具体实例对这些子句的处理加以详细介绍。
simple_select:
   SELECT opt_distinct target_list
   into_clause from_clause where_clause
   group_clause having_clause window_clause
    {
     SelectStmt *n = makeNode(SelectStmt);
     n->targetList = $3;
     n->intoClause = $4;
     n->fromClause = $5;
     n->whereClause = $6;
     n->groupClause = $7;
     n->havingClause = $8;
     n->windowClause = $9;
     $$ = (Node *)n;
    }
   | SELECT distinct_clause target_list
   into_clause from_clause where_clause
   group_clause having_clause window_clause
    {
     SelectStmt *n = makeNode(SelectStmt);
     n->distinctClause = $2;
     n->targetList = $3;
     n->intoClause = $4;
     n->fromClause = $5;
     n->whereClause = $6;
     n->groupClause = $7;
     n->havingClause = $8;
     n->windowClause = $9;
     $$ = (Node *)n;
    }
   | values_clause       { $$ = $1; }
2 子句
2.1  DISTINCT子句
DISTINCT子句对应语法定义中的标识符opt_distinct。从opt-distinct的语法结构可以看到,它可以匹配DISTINCT, ALL, DISTINCT ON (表达式列表)或者为空,用来决定SELECT语句是否去除重复的行。
当匹配到DISTINCT时, opt_distinct返回一个List,该链表的第一个ListCell的ptr-value字段置为空。
当匹配到DISTINCT ON时, opt_distinct也返回一个List,这个List中包含了跟在DISTINCTON之后的表达式的列表(星号或者表的属性等)。
当匹配到ALL或者空时, opt_distinct返回NIL,表明没有使用DISTINCT。
2.2  目标属性
目标属性是SELECT语句中所要查询的属性列表,对应着语法定义中的标识符targetList, targetList由若干个target_el组成,target_el定义为取别名的表达式、表达式以及“*”等。
target_list:
   target_el        { $$ = list_make1($1); }
   | target_list ',' target_el    { $$ = lappend($1, $3); }
  ;

target_el: a_expr AS ColLabel
    {
     $$ = makeNode(ResTarget);
     $$->name = $3;
     $$->indirection = NIL;
     $$->val = (Node *)$1;
     $$->location = @1;
    }
    /*
    * We support omitting AS only for column labels that aren't
    * any known keyword.  There is an ambiguity against postfix
    * operators: is "a ! b" an infix expression, or a postfix
    * expression and a column label?  We prefer to resolve this
    * as an infix expression, which we accomplish by assigning
    * IDENT a precedence higher than POSTFIXOP.
    */
   | a_expr IDENT
    {
     $$ = makeNode(ResTarget);
     $$->name = $2;
     $$->indirection = NIL;
     $$->val = (Node *)$1;
     $$->location = @1;
    }
   | a_expr
    {
     $$ = makeNode(ResTarget);
     $$->name = NULL;
     $$->indirection = NIL;
     $$->val = (Node *)$1;
     $$->location = @1;
    }
   | '*'
    {
     ColumnRef *n = makeNode(ColumnRef);
     n->fields = list_make1(makeNode(A_Star));
     n->location = @1;

     $$ = makeNode(ResTarget);
     $$->name = NULL;
     $$->indirection = NIL;
     $$->val = (Node *)n;
     $$->location = @1;
    }
  ;
当成功匹配一个targetList时,创建一个ResTarget结构体,该结构体中存储了该属性的全部信息。最终targetList将返回一个由ResTarget构成的List。
targetList包括若干ListCell节点,每个节点中的data字段指向结构体ResTarget,用来表示目标属性中的一项。下图展示了目标属性在内存中的组织结构。当目标属性中的某项涉及函数调用时, ResTarget中的字段val会指向结构体FunCall, FunCall的字段funcname存储函数的名称,字段args指向结构体ColumnRef构成的链表,每一个ColumnRef存储了函数调用中所使用到的表的一个属性。如果没有函数调用,则结构体ResTarget中的字段val直接指向结构体ColumnRef,存储该项目标属性所涉及的表的字段(此种情况没有在图中展示)。   
2.3  FROM子句
文件gram. y中定义的标识符from_clause表示SELECT语句中的FROM子句, from_clause由FROM关键字和fromList组成。而fromlist则由若干个标识符table_ref组成,每一个table_ref表示FROM子句中用逗号分隔的每个子项,它表示在FROM子句中出现的一个表或者一个子查询。
from_clause:
   FROM from_list       { $$ = $2; }
   | /*EMPTY*/        { $$ = NIL; }
  ;

from_list:
   table_ref        { $$ = list_make1($1); }
   | from_list ',' table_ref    { $$ = lappend($1, $3); }
  ;
标识符table_ref可以定义为关系表达式、取别名的关系表达式、带括号的SELECT语句、表连接等形式。
由于FROM子句中子项(标识符table_ref的最简单和基本的形式是关系表达式(标识符relation_expr)。因此,下面分析relation_expr的语法定义。
relation_expr:
   qualified_name
    {
      /* inheritance query, implicitly */
     $$ = $1;
     $$->inh = true;
     $$->alias = NULL;
    }
   | qualified_name '*'
    {
      /* inheritance query, explicitly */
     $$ = $1;
     $$->inh = true;
     $$->alias = NULL;
    }
   | ONLY qualified_name
    {
      /* no inheritance */
     $$ = $2;
     $$->inh = false;
     $$->alias = NULL;
    }
   | ONLY '(' qualified_name ')'
    {
      /* no inheritance, SQL99-style syntax */
     $$ = $3;
     $$->inh = false;
     $$->alias = NULL;
    }
  ;


 

relation_expr_list:
   relation_expr       { $$ = list_make1($1); }
   | relation_expr_list ',' relation_expr { $$ = lappend($1, $3); }
  ;
关系表达式relation_expr定义成qualified_name、带ONLY关键字的qualified_name等形式,最后qualified_name定义成relation_name。在成功匹配最终的标识符relation_name后,创建一个RangeVar结构体用来存储该关系的信息。
from_clause子句在分析树中同样被组织成一个List,每一个ListCell中包含一个RangeVar结构(或者其他结构)。
2.4  WHERE子句
WHERE子句中定义的是元组约束信息,对应着语法定义中的标识符where_clause。标识符where_clause定义为关键字WHERE和一个表达式(标识符a_expr)。
where_clause:
   WHERE a_expr       { $$ = $2; }
   | /*EMPTY*/        { $$ = NULL; }
  ;
由于表达式是递归定义的,因此, A_Expr结构体中字段lexpr和rexpr分别代表操作符的左右两个子表达式,字段A-Expr_kind代表操作的类型。如果该表达式是常量或者属性等(表达式树中的叶子节点),则lexpr和rexpr都为NULL。在WHERE子句中,使用到的表的属性信息用ColumnRef结构体来组织。
2.5  GROUP BY子句
GROUP BY子句的作用是根据所指定的属性进行分组,对应着语法定义中的标识符group_clause, GROUP BY子句的语法结构与WHERE子句非常相似,在此不再详细讨论。Group by子句的语法定义如下:
group_clause:
   GROUP_P BY group_by_list    { $$ = $3; }
   | /*EMPTY*/        { $$ = NIL; }
  ;
expr_list: a_expr
    {
     $$ = list_make1($1);
    }
   | expr_list ',' a_expr
    {
     $$ = lappend($1, $3);
    }
  ;

2.6  HAVING子句和ORDER BY子句
HAVING子句的作用是根据指定的条件对GROUP BY的分组进行过滤,对应于having_clause标识符。ORDER BY子句的作用是根据指定属性对整个查询的结果进行排序,对应于sort_cluse标识符。Having子句和order by子句的语法定义如下:
having_clause:
   HAVING a_expr       { $$ = $2; }
   | /*EMPTY*/        { $$ = NULL; }
  ;
sort_clause:
   ORDER BY sortby_list     { $$ = $3; }
  ;

sortby_list:
   sortby         { $$ = list_make1($1); }
   | sortby_list ',' sortby    { $$ = lappend($1, $3); }
  ;

sortby:  a_expr USING qual_all_Op opt_nulls_order
    {
     $$ = makeNode(SortBy);
     $$->node = $1;
     $$->sortby_dir = SORTBY_USING;
     $$->sortby_nulls = $4;
     $$->useOp = $3;
     $$->location = @3;
    }
   | a_expr opt_asc_desc opt_nulls_order
    {
     $$ = makeNode(SortBy);
     $$->node = $1;
     $$->sortby_dir = $2;
     $$->sortby_nulls = $3;
     $$->useOp = NIL;
     $$->location = -1;  /* no operator */
    }
  ;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值