505
阿里云
4.1 Select语句基本语法__第四章 DML_使用手册_分析型数据库-阿里云
通过DML进行计算是用户在分析型数据库中最常用的操作。目前分析型数据库对DML支持使用SELECT进行查询,以及支持INSERT、DELETE等数据修改操作(INSERT/DELETE见4.3节)。另外本节的内容需要配合附录一:函数的使用与4.2中特殊语法,以及4.4中的双计算引擎和Hint的说明来阅读。
分析型数据库中SELECT语句的基本结构如下:
SELECT
[DISTINCT]
select_expr [, select_expr ...]
[FROM table_references
[WHERE filter_condition]
[GROUP BY {col_name | expr | position}
[HAVING having_condition]
[ORDER BY {col_name | expr | position}
[ASC | DESC], ...]
[UNION ALL (SELECT select_expr..)]
[{UNION|INTERSECT|MINUS} (SELECT select_expr..)]
[LIMIT {row_count}]
下面,我们将一个完整的SELECT分为几个部分加以介绍:列投射部分(列和列表达式)、FROM/JOIN子句(表扫描、表连接与子查询)、WHERE子句(过滤表达式)、GROUP BY/HAVING子句(分组和分组后过滤)、ORDER BY子句(排序)、两个查询间的UNION [ALL]/INTERSECT/MINUS、LIMIT子句(返回行数限制)。
列投射(列和列表达式)
分析型数据库中,SELECT语句中的列投射的基本结构为:
SELECT [DISTINCT] select_expr [, select_expr ...]
其中 select_expr 可以是基本列(直接从表或子查询中选出的),也可以是列表达式(包括算数计算、聚合函数、系统UDF等)。
当 select_expr 为基本列时:
基本列是表中的列,这里的表可以是物理表也可以是虚表(物理表的别名引用或子查询产生的表)。
例如:
SELECT A.a FROM A
:指定表名和列名,表来自FROM子句,列属于FROM子句指定的表SELECT a FROM A
:仅指定列名,列属于FROM子句指定的表SELECT A.a AS x FROM A
:指定表名和列名(带别名),表来自FROM子句,列属于FROM子句SELECT a AS x FROM A
:仅指定列名(带别名),表来自FROM子句,列属于FROM子句SELECT b, a FROM A JOIN B ...
,仅指定列名,列属于FROM子句指定的第一个包含该列的表SELECT A.a FROM (SELECT A.a, b FROM A JOIN B ...)
,指定表名和列名,列属于子查询返回的列(<table>.<column>
完全匹配)SELECT a FROM (SELECT a, b FROM A JOIN B ...)
,仅指定列名,列属于子查询返回的列(<column>
完全匹配)SELECT X.a FROM (SELECT a FROM A) AS X
:指定表名和列名,表来自子查询且是别名引用,列属于子查询返回的列(<column>
完全匹配)SELECT X.x FROM (SELECT A.a AS x, b FROM A JOIN B ...) AS X
:指定表名和列名,表来自子查询且是别名引用,列属于子查询返回的列且带别名SELECT count(distinct a) from A where b = 123
, a不是分区列,且经过where条件筛选后数据量不超过100万条SELECT NULL ...
:空值列SELECT 1, 2 ...
:常量值列SELECT true ...
:常量值(boolean
类型的取值使用1
或0
)列SELECT * ...
:通配符代表所有列
暂不支持:
SELECT A.* ...
:通配符代表特定表的所有列SELECT a, b, a ...
:重复列
0.8版本中不支持但是0.9版本的Full MPP Mode支持(详见4.4节):
SELECT distinct a | count(distinct a) from A group by b
:其中a
不是分区列SELECT distinct a | count(distinct a) from A where b = 123
, a不是分区列,且经过where条件筛选后数据量超过100万条
当 select_expr 中使用列表达式时:
例如:
SELECT a + b ...
:常用算术操作符(+
,-
,*
,/
,%
),其中表达式(a
,b
)是合法的值、基本列或列表达式,但必须是数值类型SELECT min(a), UDF_EXAMPLE(a, s) ...
:系统内置或用户自定义函数,可以是值、基本列或列表达式,但数据类型要符合函数参数要求SELECT CASE WHEN a > 0 THEN a + b ELSE 0 END ...
:CASE-WHEN表达式,其中表达式(a > 0
)是合法的行过滤表达式
(参看后面),THEN
和ELSE
取值是合法的列表达式
而且数据类型相同(int
)SELECT a IS NULL, a IS NOT TRUE, a >= 0, s LIKE '%foo' ...
:合法的关系表达式
(参看后面)SELECT ! a, NOT s ...
:合法的逻辑表达式
(参看后面)
暂不支持:
SELECT a IS [NOT] TRUE, a BETWEEN 1 AND 2, a IN (1, 2), a CONTAINS (1, 2, 3)
:不支持部分关系表达SELECT a XOR b
:不支持逻辑表达式 (参看4.3节)SELECT a & b FROM A, B
:不支持位操作
当 select_expr 为列聚集函数表达式时:
包含任何聚集函数的列表达式,即聚集表达式:
例如:
SELECT COUNT(*)
:常用聚合函数,详见附件中函数表SELECT UDF_SYS_COUNT_COLUMN(a) FROM A
:系统内置聚合函数(UDF_SYS_...
)SELECT SUM(CASE WHEN ... THEN ... ELSE ... END)
:聚合表达式(SUM(...)
)套列普通表达式(CASE WHEN ...
)做为其子表达式SELECT SUM(a) / COUNT(a) FROM A
:列普通表达式(/
)套聚合表达式(做为其子表达式)
0.8版本中不支持但是0.9版本的Full MPP Mode支持(详见4.4节):
SELECT a + COUNT(*) FROM A
:普通表达式(+
)不能同时套普通表达式(a
)和聚合表达式(COUNT(...)
);SELECT SUM(COUNT(*))
:聚合表达式不能套聚合表达式做为其子表达式;
FROM/JOIN子句(表扫描、连接与子查询)
用法:
FROM table_references
或
FROM table_referencesA as table_aliasA JOIN table_referencesB as table_aliasB on join_conditions
或
FROM (SELECT ...) as aliasA JOIN table_referencesB as table_aliasB on join_conditions
或
FROM (SELECT ...) as aliasA JOIN (SELECT ...)as aliasB on join_conditions
例如:
FROM A
:指定表FROM (SELECT ...)
:子查询FROM A JOIN B ON A.a = B.b JOIN C ON A.a = C.c
:单表或多表连接,默认是符合条件记录的笛卡尔集。需要注意的是,目前分析型数据库中使用JOIN时若一方是物理表,那么物理表参与JOIN的列必须是分区列并且已建立HASH索引FROM (SELECT ...) AS X JOIN A on X.x = A.a
:表、子查询和JOIN结合使用SELECT ... FROM A JOIN (SELECT ...)
:在V0.6.x及后续版本支持SELECT ... FROM (SELECT ...) JOIN (SELECT ...)
:两个子查询之间的Join,在V0.6.x及后续版本支持
不支持或语义错误:
SELECT ... FROM A FULL JOIN B
:不支持全连接;SELECT ... FROM A RIGHT JOIN B
:不支持右连接,需要转换为左连接;SELECT ... FROM A SEMI JON B
:不支持半连接;SELECT ... FROM A, B
:单表或多表连接,但没有ON条件SELECT ... FROM A, B WHERE A.a = B.b
:单表或多表连接在WHERE子句中有隐含ON条件,但是没有on子句的,暂不支持
0.8版本中两个表关联可运行的充要条件(四原则):
(1)两个表均为事实表且在同一个表组,或两个表中有一个是维度表。
(2)两个表均为事实表且拥有相同的一级分区列,或两个表中有一个是维度表。
(3)两个表均为事实表且关联条件(on)中至少含有一个条件是两个表各自的分区列的等值关联条件,或两个表中有一个是维度表。
(4)关联条件(on)中的条件两端有有效的HashMap索引
0.9版本中两个表关联可加速运行的条件:
(1)两个表均为事实表且在同一个表组,或两个表中有一个是维度表。
(2)两个表均为事实表且拥有相同的一级分区列,或两个表中有一个是维度表。
(3)两个表均为事实表且关联条件(on)中至少含有一个条件是两个表各自的分区列的等值关联条件,或两个表中有一个是维度表。
0.9版本若使用Full MPP Mode支持任意形态的表关联(详见4.4节),该功能目前邀请少数客户测试,后续全面开放。
WHERE子句(过滤表达式)
在过滤表达式中,单个条件之间可以用AND和OR进行连接,支持括号决定条件表达式的优先级,亦支持表达式嵌套。
像普通的SQL一样,单个条件的组成是一个布尔判断。暨无论如何组合,单个条件最终是一个返回True/False的表达式。在最简单的情况下,单个条件由左侧的主体、中间的比较操作符和右侧的断言值组成。
例如:column_name IS NOT NULL 中, column_name 为布尔主体,IS NOT为比较操作符,NULL为断言值。
分析型数据库中比较操作符支持 = 、 >= 、 > 、 <= 、 < 、 <> 、 != 等基本操作符,也支持IS、IN、CONTAINS、BETWEEN…AND… 、LIKE这样的关系操作符,并且关系操作符均支持其反义的版本(IS NOT 、 NOT IN 、 NOT LIKE等)。
布尔主体可以是一个列,也可以是表达式的嵌套。
例如:
WHERE a > 0
: 关系表达式(>
,>=
,<
,<=
,=
,<>
,!=
)WHERE a IS [NOT] NULL
:关系表达式,判断是否为空值WHERE a BETWEEN 1 AND 10
:对于表达式(a
)是数字类型(long
,int
,short
,double
,boolean
)和时间类型(date
,time
,timestamp
)支持WHERE s LIKE '%sample'
:对于表达式(s
)是字符串(string
)类型支持WHERE a IN (1,2,3)
:对于表达式(a
)是多值列类型支持WHERE a IN (select a from dim_table where c=1)
:对于对于表dim_table是维度表,支持IN后带子查询(V0.6.2之后的版本支持)WHERE a CONTAINS (1,2,3)
:对于表达式(a
)是多值列类型支持WHERE a > 0 AND b > 0
:逻辑表达式WHERE (a >0 OR b > 0) AND c > 0
:支持括号决定条件表达式的优先级WHERE (CASE WHEN (a + b) > 0 THEN 0 ELSE 1 END) != 0 AND UDF_EXAMPLE(a, b) > 0
:表达式嵌套。
不支持或语义错误:
WHERE EXISTS (SELECT...)
:不支持WHERE a = ANY (SELECT ...)
:不支持WHERE a = ALL (SELECT ...)
:不支持
0.8版本中不支持但是0.9版本的Full MPP Mode支持(详见4.4节):
WHERE a IN (select a from fact_table where c=1)
: fact_table不是维度表的情况下0.8版本不支持
GROUP BY/HAVING子句(分组和分组后过滤)
GROUP BY子句的用法:
GROUP BY {col_expr}
col_expr为列(表中的列或子查询、别名产生的列)。
例如:
- `… FROM A GROUP BY a:仅指定列
- `… FROM A GROUP BY A.a:同时指定表名和列
GROUP BY s, a IS NULL, b + c, UDF_EXAMPLE(d)
:一个或多个列表达式SELECT a, SUM(a) FROM A GROUP BY a, s:可以包含不属于列透视的列表达式(
s`)- `… FROM (SELECT A.a AS x, b FROM A JOIN B …) AS X JOIN C … GROUP BY b, c, X.x:包含在子查询或多表连接的一个或多个列表达式
- `SELECT CASE WHEN a > 1 THEN ‘Y’ ELSE ‘N’ END AS x … GROUP BY x :别名引用产生的列表达式
SELECT a, b, c ... GROUP BY 3, 1
:按位置引用列投射的列表达式
0.8版本中不支持但是0.9版本的Full MPP Mode支持(详见4.4节):
... FROM A GROUP BY s ORDER BY COUNT(a) LIMIT 100
:分区表达式(s
)不是分区列(a
)同时又有TOP-N(ORDER BY COUNT(a) LIMIT 100
)0.8版本下计算的结果可能是不精确的(详见4.3节)
HAVING子句的用法:
HAVING子句用于在GROUP BY子句执行后对分组后的结果进行过滤。支持使用列投射和聚合表达式后的结果进行过滤。
HAVING having_condition
例如:
SELECT a, sum(length(s)) AS x FROM A JOIN B ON A.a = B.b GROUP BY a HAVING (CASE WHEN (x / a > 1) THEN a ELSE 0 END) != 0
:分组表达式(a
)是分区列,HAVING表达式是基于列表达式 (a
,sum(length(s))
,s
)的行过滤表达式
0.8版本中不支持但是0.9版本的Full MPP Mode支持(详见4.4节):
SELECT s, count(a) AS x FROM A GROUP BY s HAVING x > 1
:分组表达式(s
)不是分区列(a
)
ORDER BY子句(排序)
例如:
SELECT a FROM A ORDER BY a DESC LIMIT 100
:按照分区列(a
)排序并返回TOP-N(100
)SELECT a FROM A ORDER BY (a + b) DESC LIMIT 100
:按照非分区列(a
)排序并返回TOP-N(100
)SELECT a, COUNT(a) FROM A GROUP BY a ORDER BY x
:按照分区列(a
)分组聚合再排序
0.8版本中不支持但是0.9版本的Full MPP Mode支持(详见4.4节):
SELECT a + b, COUNT(1) AS x FROM A GROUP BY a + b ORDER BY x
:0.8版本下按照非分区列表达式(a+b
)分组聚合再取TOP-N是非精确的(详见4.3)
UNION [ALL]/INTERSECT/MINUS子句
UNION/INTERSECT/MINUS
0.8版本下仅支持操作字段为分区列,但是0.9版本的Full MPP Mode无限制(详见4.4节)。
UNION ALL无任何限制。
LIMIT子句(返回行数限制)
示例:
SELECT ... LIMIT 100
:返回行限制为100行
不支持:
SELECT ... LIMIT 100, 50
:不支持带偏移量的返回行限制
需要注意的是,分析型数据库会对通过SELECT语句进行查询的返回行数做全局的最大限制,公共云上目前为10000行,若不加LIMIT或LIMIT行数超过10000,则只会返回10000行。
最后更新:2016-11-24 11:23:46
上一篇:
3.6 ECU管理__第三章 DDL_使用手册_分析型数据库-阿里云
下一篇:
4.2 逻辑表达式和特殊语法__第四章 DML_使用手册_分析型数据库-阿里云
配置媒体工作流__开发人员指南_视频点播-阿里云
为磁盘设置自动快照策略__快照_用户指南_云服务器 ECS-阿里云
PostgreSQLWriter__Writer插件_使用手册_数据集成-阿里云
网站日志分析__场景化分析_Quick BI-阿里云
申请外网连接串__实例管理_API 参考_云数据库 RDS 版-阿里云
APP设备统计__API列表_OpenAPI 1.0_移动推送-阿里云
MQTT 简介__MQTT 接入(物联)_消息队列 MQ-阿里云
使用金融云OSS__使用金融云产品_金融云-阿里云
获取应用列表__应用管理类 API_Open API 参考_企业级分布式应用服务 EDAS-阿里云
DnsProductType__数据类型_API文档_云解析-阿里云
相关内容
常见错误说明__附录_大数据计算服务-阿里云
发送短信接口__API使用手册_短信服务-阿里云
接口文档__Android_安全组件教程_移动安全-阿里云
运营商错误码(联通)__常见问题_短信服务-阿里云
设置短信模板__使用手册_短信服务-阿里云
OSS 权限问题及排查__常见错误及排除_最佳实践_对象存储 OSS-阿里云
消息通知__操作指南_批量计算-阿里云
设备端快速接入(MQTT)__快速开始_阿里云物联网套件-阿里云
查询API调用流量数据__API管理相关接口_API_API 网关-阿里云
使用STS访问__JavaScript-SDK_SDK 参考_对象存储 OSS-阿里云