Fork me on GitHub

SQL内置函数手册

SQL内置函数使用大全

本文中总结了SQL中常用的内置函数,包含通用聚合函数、安全检测函数、数学统计函数、字符串函数

通用聚合函数

语句 含义 示例
arbitrary(x) 随机返回x列中的一个值。 latency > 100 | select arbitrary(method)
avg(x) 计算x列的算数平均值。 latency > 100 | select avg(latency)
checksum(x) 计算某一列的checksum,返回base64编码。 latency > 100 | select checksum(method)
count(*) 表示所有的行数。 -
count(x) 计算某一列非null的个数。 latency > 100 | select count(method)
count(数字) count(数字),如count(1),等同于count(*),表示所有的行数。 -
count_if(x) 计算x=true的个数。 latency > 100 | select count_if(url like ‘%abc’)
geometric_mean(x) 计算某一列的几何平均数。 latency > 100 | select geometric_mean(latency)
max_by(x,y) 返回当y取最大值时,x当前的值。 查询延时最高的时候,对应的method:latency>100 | select max_by(method,latency)
max_by(x,y,n) 返回y最高的n行,对应的x的值。 查询延时最高的3行,对应的method:latency > 100 | select max_by(method,latency,3)
min_by(x,y) 返回当y取最小值时,x当前的值。 查询延时最低的请求,对应的method:* | select min_by(x,y)
min_by(x,y,n) 返回y最小的n行,对应的x的值。 查询延时最小的3行,对应的method: * | select min_by(method,latency,3)
max(x) 返回最大值。 latency > 100| select max(inflow)
min(x) 返回最小值。 latency > 100| select min(inflow)
sum(x) 返回x列的和。 latency > 10 | select sum(inflow)
bitwise_and_agg(x) 对某一列的所有数值做and计算。 -
bitwise_or_agg(x) 对某一列的数值做or计算。 -

安全检测函数

函数名 含义 样例
security_check_ip 检查IP是否安全,其中:返回1:命中,表示不安全返回0:未命中 select security_check_ip(real_client_ip)
security_check_domain 检查Domain是否安全,其中:返回1:命中,表示不安全返回0:未命中 select security_check_domain(site)
security_check_url 检查URL是否安全,其中:返回1:命中,表示不安全返回0:未命中 select security_check_domain(concat(host, url))

Map映射函数

函数 含义 示例
下标运算符[] 获取map中某个Key对应的结果。 -
histogram(x) 按照x的每个值进行GROUP BY并计算count。语法相当于select count group by x 说明 返回结果为JSON格式。 latency > 10 | select histogram(status),等同于latency > 10 | select count(1) group by status
histogram_u(x) 按照x的每个值进行GROUP BY并计算count。说明 返回结果为多行多列。 latency > 10 | select histogram(status),等同于latency > 10 | select count(1) group by status
map_agg(Key,Value) 返回Key、Value组成的map,并返回每个Key随机的Value。 latency > 100 | select map_agg(method,latency)
multimap_agg(Key,Value) 返回Key、Value组成的多Value map,并返回每个Key的所有的Value。 latency > 100 | select multimap_agg(method,latency)
cardinality(x) → bigint 获取map的大小。 -
element_at(map``, key) → V 获取Key对应的Value。 -
map() → map`` 返回一个空的map。 -
map(array, array) → map`` 将两个数组转换成Key、Value组成的Map。 SELECT map(ARRAY[1,3], ARRAY[2,4]); — {1 -> 2, 3 -> 4}
map_from_entries(array>) → map`` 把一个多维数组转化成map。 SELECT map_from_entries(ARRAY[(1, ‘x’), (2, ‘y’)]); — {1 -> ‘x’, 2 -> ‘y’}
map_concat(map1, map2, …, mapN) → map 求多个map的并集,如果某个Key存在于多个map中,则取最后一个。 -
map_filter(map, function) → map 请参见Lambda函数中map_filter函数。 -
map_keys(x) → array 获取map中所有的Key并以array的形式返回。 -
map_values(x) → array 获取map中所有的Value并以array的形式返回。 -

估算函数

桶是按照聚集程度均分的,每个结果里显示这个区域的均值和个数

函数 说明 示例
approx_distinct(x) 估算x列的唯一值的个数。 -
approx_percentile(x,percentage) 对于x列排序,找出大约处于percentage位置的数值。 找出位于一半位置的数值:approx_percentile(x,0.5)
approx_percentile(x, percentages) approx_percentile(x,percentage)用法类似,但可以指定多个percentage,找出每个percentage对应的数值。 approx_percentile(x,array[0.1,0.2])
numeric_histogram(buckets, Value) 对于数值列,分多个桶进行统计。即把Value一列,分到桶中,桶的个数为buckets。返回内容为每个桶的Key及对应的count数值,相当于针对数值的select count group by说明 返回结果的格式为JSON。 对于POST请求,把延时分为10个桶,查看每个桶的大小:method:POST | select numeric_histogram(10,latency)
numeric_histogram_u(buckets, Value) 对于数值列,分多个桶进行统计。即把Value一列,分到桶中,桶的个数为buckets。返回内容为每个桶的Key及对应的count数值,相当于针对数值的select count group by说明 返回结果的格式为多行多列。 对于POST请求,把延时分为10个桶,查看每个桶的大小:method:POST | select numeric_histogram_u(10,latency)

数学统计函数

语句 含义 示例
corr(y, x) 给出两列的相关度,结果从0到1。 latency>100| select corr(latency,request_size)
covar_pop(y, x) 计算总体协方差。 latency>100| select covar_pop(request_size,latency)
covar_samp(y, x) 计算样本协方差。 latency>100| select covar_samp(request_size,latency)
regr_intercept(y, x) 返回输入值的线性回归截距。 y是依赖值, x是独立值。 latency>100| select regr_intercept(request_size,latency)
regr_slope(y,x) 返回输入值的线性回归斜率。 y是依赖值, x是独立值。 latency>100| select regr_slope(request_size,latency)
stddev(x)stddev_samp(x) 返回x列的样本标准差。 latency>100| select stddev(latency)
stddev_pop(x) 返回x列的总体标准差。 latency>100| select stddev_pop(latency)
variance(x)var_samp(x) 计算x列的样本方差。 latency>100| select variance(latency)
var_pop(x) 计算x列的总体方差。 latency>100| select variance(latency)

数学计算函数

支持的运算符号:+、-、*、/、%;可以用在select句子中

函数名 含义
abs(x) 返回x列的绝对值。
cbrt(x) 返回x列的立方根。
ceiling(x) 返回x列向上最接近的整数。
cosine_similarity(x,y) 返回稀疏向量x和y之间的余弦相似度。
degrees 把弧度转化为度。
e() 返回自然常数。
exp(x) 返回自然常数的指数。
floor(x) 返回x向下最接近的整数。
from_base(string,radix) 以radix进制解释string。
ln(x) 返回自然对数。
log2(x) 返回以2为底,x的对数。
log10(x) 返回以10为底,x的对数。
log(x,b) 返回以b为底,x的对数。
pi() 返回π。
pow(x,b) 返回x的b次幂。
radians(x) 把度转化成弧度。
rand() 返回随机数。
random(0,n) 返回[0,n)随机数。
round(x) x四舍五入。
round(x, y) 对x保留y个小数为,例如round(1.012345,2) = 1.01。
sqrt(x) 返回x的平方根。
to_base(x, radix) 把x以radix进制表示。
truncate(x) 丢弃掉x的小数部分。
acos(x) 反余弦。
asin(x) 反正弦。
atan(x) 反正切。
atan2(y,x) y/x的反正切。
cos(x) 余弦。
sin(x) 正弦。
cosh(x) 双曲余弦。
tan(x) 正切。
tanh(x) 双曲正切。
infinity() 返回正无穷的数值。
is_infinity(x) 判断值是否是无限值。
is_finity(x) 判断是否是有限值。
is_nan(x) 判断是否是非数值。

字符串函数

函数名 含义
chr(x) 把int类型转化成对应的ASCII码,例如chr(65)结果为A
codepoint (x) 把一个ASCII码转化成int类型的编码,例如codepoint('A')结果为65
length(x) 字段长度。
levenshtein_distance(string1, string2) 返回两个字符串的最小编辑距离。
lower(string) 转化成小写。
lpad(string, size, padstring) string对齐到size大小,如果小于size,用padstring从左侧补齐到;如果大于size则截取到size个。
rpad(string, size, padstring) 类似lpad,从右侧补齐string
ltrim(string) 删掉左侧的空白字符。
replace(string, search) 把字符串中string中的search删掉。
replace(string, search,rep) 把字符串中string中的search替换为rep
reverse(string) 翻转string。
rtrim(string) 删掉字符串结尾的空白字符。
split(string,delimeter,limit) 把字符串分裂成array,最多取limit个值。生成的结果为数组,下标从1开始。
split_part(string,delimeter,offset) 把字符串分裂成array,取第offset个字符串。生成的结果为字符串。
split_to_map(string, entryDelimiter, keyValueDelimiter) → map string按照entryDelemiter分割成多个entry,每个entry再按照keyValueDelimiter划分成key value。最终返回一个map。
position(substring IN string) 获取string中,substring最先开始的位置。
strpos(string, substring) 查找字符串中的子串的开始位置。返回结果从1开始,如果不存在则返回0。
substr(string, start) 返回字符串的子串,start下标从1开始。
substr(string, start, length) 返回字符串的子串,start下标从1开始,length指定子串的长度。
trim(string) 删掉字符串开头和结尾的空白字符。
upper(string) 转化为大写字符。
concat(string,string......) 把两个或多个字符串拼接成一个字符串。
hamming_distance (string1,string2) 获得两个字符串的海明距离。

日期和时间函数

函数类型

日期和时间函数主要是包含:

  • 日期函数
  • 时间函数
  • 区间函数
  • 时序补全函数

日期时间类型

  1. 时间戳类型unixtime:以int类型表示从1970年1月1日开始的秒数,例如1512374067表示的时间是Mon Dec 4 15:54:27 CST 2017。日志服务每条日志中内置的时间__time__即为这种类型。
  2. timestamp类型:以字符串形式表示,例如:2017-11-01 13:30:00

日期函数

函数名 含义 样例
current_date 当天日期。 latency>100| select current_date
current_time 当前时间。 latency>100| select current_time
current_timestamp 结合current_date 和current_time的结果。 latency>100| select current_timestamp
current_timezone() 返回时区。 latency>100| select current_timezone()
from_iso8601_timestamp(string) 把iso8601时间转化成带时区的时间。 latency>100| select from_iso8601_timestamp(iso8601)
from_iso8601_date(string) 把iso8601转化成天。 latency>100| select from_iso8601_date(iso8601)
from_unixtime(unixtime) 把unix时间转化为时间戳。 latency>100| select from_unixtime(1494985275)
from_unixtime(unixtime,string) 以string为时区,把unixtime转化成时间戳。 latency>100| select from_unixtime (1494985275,'Asia/Shanghai')
localtime 本地时间。 latency>100| select localtime
localtimestamp 本地时间戳。 latency>100| select localtimestamp
now() 等同于current_timestamp -
to_unixtime(timestamp) timestamp转化成unixtime。 *| select to_unixtime('2017-05-17 09:45:00.848 Asia/Shanghai')

时间函数

  • date_format(timestamp, format)
  • date_parse(string, format)
函数名 含义 样例
date_format(timestamp, format) 把timestamp转化成以format形式表示。 latency>100
date_parse(string, format) 把string以format格式解析,转化成timestamp。 latency>100

格式说明

格式 描述
%a 星期的缩写,即Sun、Sat等。
%b 月份的缩写,即Jan、Dec等。
%c 月份,数值类型,即1~12。
%D 每月的第几天,带后缀,即0th、1st、2nd、3rd等。
%d 每月第几天,十进制格式,范围为01~31。
%e 每月第几天,十进制格式,范围为1~31。
%H 小时,24小时制。
%h 小时,12小时制。
%I 小时,12小时制。
%i 分钟,数值类型,范围为00~59。
%j 每年的第几天,范围为001~366。
%k 小时,范围为0~23。
%l 小时,范围为1~12。
%M 月份的英文表达,范围为January~December。
%m 月份,数值格式,范围为01~12。
%p AM或PM。
%r 时间,12小时制,格式为hh:mm:ss AM/PM
%S 秒,范围为00~59。
%s 秒,范围为00~59。
%T 时间,24时制,格式为 hh:mm:ss
%V 每年的第几周,星期日是一周的第一天。范围为01~53,与%X同时使用。
%v 每年的第几周,星期一是一周的第一天。范围为01~53,与%x同时使用。
%W 星期几的名称,范围为Sunday到Saturday。
%w 一周的第几天, 星期日为第0天。
%Y 4 位数的年份。
%y 2位数的年份。
%% %转义字符。

时间段对齐函数

按照秒、分钟、小时、日、月、年等进行对齐

1
date_trunc(unit,x)
  • x是一个timestamp类型,也可以是unix time
  • date_trunc只能按照固定时间间隔统计
1
2
3
4
5
6
*|select  date_trunc('minute' ,  __time__)  as t,
truncate (avg(latency) ) ,
current_date
group by t
order by t desc
limit 60

时间间隔函数

时间间隔函数用来执行时间段相关的运算,如在日期中添加或减去指定的时间间隔、计算两个日期之间的时间

  • date_add(unit, value, timestamp):在timestamp的基础上加上value个unit;如果value是负值,则进行减法
  • date_diff(unit, timestamp1, timestamp2):计算两个timestamp之间差几个unit
函数名 含义 样例
date_add(unit, value, timestamp) timestamp上加上valueunit。如果要执行减法,value使用负值。 date_add('day', -7, '2018-08-09 00:00:00') 表示8月9号之前7天
date_diff(unit, timestamp1, timestamp2) 表示timestamp1timestamp2之间相差几个unit date_diff('day', '2018-08-02 00:00:00', '2018-08-09 00:00:00') = 7

函数区间单位

单位 说明
millisecond 毫秒
second
minute 分钟
hour 小时
day
week
month
quarter 季度,即三个月
year

时序补全函数time_series

时序补全函数time_series必须和group by time order by time一起使用,且order by不支持desc排序方式

函数格式:

1
time_series(time_column, window, format, padding_data)

参数说明:

参数 说明
time_column 时间列,例如日志服务提供的默认时间字段__time__。格式为long类型或timestamp类型。
window 窗口大小,由一个数字和单位组成。单位为s(秒)、m(分)、H (小时)、或d(天)。例如2h、5m、3d。
format MySQL时间格式,表示最终输出的格式。
padding_data 表示补全的内容,包括:0:补零。null:补null。last:补上一个值。next:补下一个值。avg:补前后的平均值。

URL函数

URL函数支持从标准URL路径中提取字段,一个标准的URL如下:

1
[protocol:][//host[:port]][path][?query][#fragment]
函数名 含义 示例
输入样例 输出结果
url_extract_fragment(url) 提取出URL中的fragment,结果为varchar类型。 *| select url_extract_fragment('https://sls.console.aliyun.com/#/project/dashboard-demo/categoryList') 输出结果为/project/dashboard-demo/categoryList
url_extract_host(url) 提取出URL中的host,结果为varchar类型。 *|select url_extract_host('http://www.aliyun.com/product/sls') 输出结果为www.aliyun.com
url_extract_parameter(url, name) 提取出URL中的query中name对应的参数值,结果为varchar类型。 *|select url_extract_parameter('http://www.aliyun.com/product/sls?userid=testuser','userid') 输出结果为testuser
url_extract_path(url) 提取出URL中的path,结果为varchar类型。 *|select url_extract_path('http://www.aliyun.com/product/sls?userid=testuser') 输出结果为/product/sls
url_extract_port(url) 提取出URL中的端口,结果为bigint类型。 *|select url_extract_port('http://www.aliyun.com:80/product/sls?userid=testuser') 输出结果为80
url_extract_protocol(url) 提取出URL中的协议,结果为varchar类型。 *|select url_extract_protocol('http://www.aliyun.com:80/product/sls?userid=testuser') 输出结果为http
url_extract_query(url) 提取出URL中的query,结果为varchar类型。 *|select url_extract_query('http://www.aliyun.com:80/product/sls?userid=testuser') 输出结果为userid=testuser
url_encode(value) 对url进行转义编码。 *|select url_encode('http://www.aliyun.com:80/product/sls?userid=testuser') 输出结果为http%3a%2f%2fwww.aliyun.com%3a80%2fproduct%2fsls%3fuserid%3dtestuser
url_decode(value) 对url进行解码。 *|select url_decode('http%3a%2f%2fwww.aliyun.com%3a80%2fproduct%2fsls%3fuserid%3dtestuser') 输出结果为http://www.aliyun.com:80/product/sls?userid=testuser

正则式函数

函数名 含义 样例
regexp_extract_all(string, pattern) 返回字符串中命中正则式的所有子串,返回结果是一个字符串数组。 *| SELECT regexp_extract_all('5a 67b 890m', '\d+'),结果为['5','67','890']*|SELECT regexp_extract_all('5a 67a 890m', '(\d+)a') 结果为['5a','67a']
regexp_extract_all(string, pattern, group) 返回字符串中命中正则式的第group个()内部分,返回结果是一个字符串数组。 *| SELECT regexp_extract_all(‘5a 67a 890m’, ‘(\d+)a’,1) 结果为[‘5’,’67’]
regexp_extract(string, pattern) 返回字符串命中的正则式的第一个子串 *|SELECT regexp_extract('5a 67b 890m', '\d+') 结果为'5'
regexp_extract(string, pattern,group) 返回字符串命中的正则式的第group个()内的第1个子串 *|SELECT regexp_extract('5a 67b 890m', '(\d+)([a-z]+)',2) 结果为'a'
regexp_like(string, pattern) 判断字符串是否命中正则式,返回bool类型,正则式可以只命中字符串的一部分。 *|SELECT regexp_like('5a 67b 890m', '\d+m') 结果为true
regexp_replace(string, pattern, replacement) 把字符串中命中正则式的部分替换成replacement。 *|SELECT regexp_replace('5a 67b 890m', '\d+','a') 结果为'aa ab am'
regexp_replace(string, pattern) 把字符串中命中正则式的部分删除,相当于regexp_replace(string,patterm,'') *|SELECT regexp_replace('5a 67b 890m', '\d+') 结果为'a b m'
regexp_split(string, pattern) 使用正则式把字符串切分成数组。 *|SELECT regexp_split('5a 67b 890m', '\d+') 结果为['a','b','m']

JSON函数

JSON主要有两种结构:map和array。如果一个字符串解析成JSON失败,那么返回的是null。

  • json_parse(string):将字符串转成JSON类型
  • json_format(json):将json类型转成字符串
函数名 含义 样例
json_parse(string) 把字符串转化成JSON类型。 SELECT json_parse('[1, 2, 3]') 结果为JSON类型数组
json_format(json) 把JSON类型转化成字符串。 SELECT json_format(json_parse('[1, 2, 3]')) 结果为字符串
json_array_contains(json, value) 判断一个JSON类型数值,或者一个字符串(内容是一个JSON数组)是否包含某个值。 SELECT json_array_contains(json_parse('[1, 2, 3]'), 2)或 SELECT json_array_contains('[1, 2, 3]', 2)
json_array_get(json_array, index) json_array_contains,是获取一个JSON数组的某个下标对应的元素。 SELECT json_array_get('["a", "b", "c"]', 0)结果为'a'
json_array_length(json) 返回JSON数组的大小。 SELECT json_array_length('[1, 2, 3]') 返回结果3
json_extract(json, json_path) 从一个JSON对象中提取值,JSON路径的语法类似$.store.book[0].title,返回结果是一个JSON对象。 SELECT json_extract(json, '$.store.book');
json_extract_scalar(json, json_path) 类似json_extract,但是返回结果是字符串类型。 -
json_size(json,json_path) 获取JSON对象或数组的大小。 SELECT json_size('[1, 2, 3]') 返回结果3

类型转换函数

类型转换函数用于在查询中转换指定值或指定列的数据类型。

函数格式

  • 在查询中将某一列(字段)或某一个值转换成指定类型。其中,如果某一个值转换失败,将终止整个查询
1
cast([key|value] as type)
  • 在查询中将某一列(字段)或某一个值转换成指定类型。如果某一个值转换失败,该值返回NULL,并跳过该值继续处理

参数

参数 说明
key 日志的Key,表示将该字段所有的值都转换成指定类型
value 常量值,表示将某个值转换成指定类型

示例

  • 将数字123转换为字符串(varchar)格式:

    1
    cast(123 AS varchar)
  • 将uid字段转换为字符串(varchar)格式:

    1
    cast(uid AS varchar)

IP地理函数

IP 地理函数可以识别一个 IP 是内网 IP还是外网 IP,也可以判断 IP 所属的国家、省份、城市

常用函数

函数名 含义 样例
ip_to_domain(ip) 判断 IP 所在的域,是内网还是外网。返回 intranet 或 internet。 SELECT ip_to_domain(ip)
ip_to_country(ip) 判断 IP 所在的国家。 SELECT ip_to_country(ip)
ip_to_province(ip) 判断 IP 所在的省份。 SELECT ip_to_province(ip)
ip_to_city(ip) 判断 IP 所在的城市。 SELECT ip_to_city(ip)
ip_to_geo(ip) 判断 IP 所在的城市的经纬度,范围结果格式为纬度,经度 SELECT ip_to_geo(ip)
ip_to_city_geo(ip) 判断 IP 所在的城市的经纬度,返回的是城市经纬度,每个城市只有一个经纬度,范围结果格式为纬度,经度 SELECT ip_to_city_geo(ip)
ip_to_provider(ip) 获取 IP 对应的网络运营商。 SELECT ip_to_provider(ip)
ip_to_country(ip,'en') 判断 IP 所在的国家,返回国家码。 SELECT ip_to_country(ip,'en')
ip_to_country_code(ip) 判断 IP 所在的国家,返回国家码。 SELECT ip_to_country_code(ip)
ip_to_province(ip,'en') 判断 IP 所在的省份,返回英文省名或者中文拼音。 SELECT ip_to_province(ip,'en')
ip_to_city(ip,'en') 判断 IP 所在的城市,返回英文城市名或者中文拼音。 SELECT ip_to_city(ip,'en')

使用demo

  • 过滤掉内网请求,查看top10的网络访问省份
1
2
3
4
5
* | select count(1) as pv, ip_to_province(ip) as province   -- 判断省份
where ip_to_domain(ip) != 'intranet' -- 过滤内网
group by province -- 分组
order by desc -- 降序
limit 10 -- 取出前10个
  • 查看不同国家的平均响应延时、最大响应延时以及最大延时对应的 request

    1
    2
    3
    4
    5
    6
    select avg(latency),
    max(latency),
    max_by(requestId, latency),
    ip_to_country(ip) as country
    group by country
    limit 100

地理函数

常用的地理函数包含:

  • geohash(string)
  • geohash(lat, lon)
函数名 含义 样例
geohash(string) 将纬度、经度用geohash编码,string为字符串类型,内容是纬度、逗号、经度。 select geohash('34.1,120.6')= 'wwjcbrdnzs'
geohash(lat,lon) 将纬度、经度用geohash编码,参数分别是纬度和经度。 select geohash(34.1,120.6)= 'wwjcbrdnzs'

Group by用法

GROUP BY 支持多列。GROUP BY支持通过SELECT的列的别名来表示对应的KEY

1
2
select avg(latency), projectName, date_trunc('hour', __time__) as hour   -- 取别名
group by ProjectName, hour

group by 支持grouping sets, cube, rollup

1
2
3
method:PostLogstoreLogs |select avg(latency)   group by cube(projectName,logstore)
method:PostLogstoreLogs |select avg(latency) group by GROUPING SETS ( ( projectName,logstore), (projectName,method))
method:PostLogstoreLogs |select avg(latency) group by rollup(projectName,logstore)

在group by中提取非agg列:如果使用了group by语法,那么在select时,只能选择select group by 的列原始内容,或者对任意列进行聚合计算,不允许获取非group by列的内容

错误语法

1
*| select a,b, count(c),group by a   -- b行由多个可供选择,系统不知道选择哪个

解决办法:使用arbitrary函数

1
*| select a, arbitrary(b), count(c) group by a

窗口函数

窗口函数用处

在日常工作中,经常会遇到需要在每组内排名,比如下面的业务需求:

排名问题:每个部门按业绩来排名
topN问题:找出每个部门排名前N的员工进行奖励

面对这类需求,就需要使用sql的高级功能窗口函数了。

什么是窗口函数

窗口函数,也叫OLAP函数(online anallytical processing,联合分析处理)。窗口函数是用来跨行计算的。普通的SQL聚合函数是只能用来处理计算一行内的结果,窗口函数可以跨行计算,并且把结果填到每行中

基本语法

1
2
<窗口函数> over (partition by <用于分组的列名>
order by <用于排序的列名>)

<窗口函数>的位置可以放置两种函数:

  1. 专用窗口函数:rank、dense_rank、row_number
  2. 聚合函数:sum、avg、count、max、min

因为窗口函数是对where或者group by子句处理后的结果进行操作,所以窗口函数原则上只能写在select子句中

使用demo

1
2
3
4
5
select key1,key2,value
rank() over (pratition by key2
order by value desc) as rnk
from orders
order by key1, rnk

函数

函数 含义
rank() 在窗口内,按照某一列排序,返回在窗口内的序号。
row_number() 返回在窗口内的行号。
first_value(x) 返回窗口内的第一个value,一般用法是窗口内数值排序,获取最大值。
last_value(x) 含义和first value相反。
nth_value(x, offset) 窗口内的第offset个数。
lead(x,offset,defaut_value) 窗口内x列某行之后offset行的值,如果不存在该行,则取default_value。
lag(x,offset,defaut_value) 窗口内x列某行之前offset行的值,如果不存在该行,则取default_value。

demo-1

如果想对每个班级内按照成绩排名:

得到如下结果

1
2
3
4
select *,
rank() over (partition by 班级 -- rank()是排序的函数;同时对表分组
order by 成绩 desc) as ranking -- 对分组后的结果进行降序
from 班级表

关键字:

  • rank() over
  • partition by
  • order by

demo-2

  • 查询在整个公司的人员中,获取每个人的薪水在部分内的排名
1
2
3
4
select department, personId, sallary,
rank() over (Partition by department
order by sallary desc) as sallary_rank
order by department, sallary_rank
  • 在整个公司的人员中,获取每个人的薪水在部门中的占比
1
select department, personId, sallery * 1.0 / sum(sallery) over (partition by department) as sallary_percentage

having语法

having用于过滤group by之后的聚合计算结果,where是在聚合计算之前过滤原始数据

order by语法

对输出结果进行排序

1
order by column [desc|asc]

实例demo

1
2
3
4
select avg(latency) as avg_latency, projectName
group by projectName
having avg(latency) > 570000
order by avg_latency desc;

limit语法

用法

用于限制输出结果的行数

1
2
limit N   -- 取前N行数据
limit S, N -- 从S行开始,取出N行数据
  • 不支持将limit语法用于子查询内部
  • 翻页的offset不能超过1,000,000,即S+N必须小于1,000,000
  • N不能超过10,000

demo

  • 只获取100行结果:

    1
    * | select distinct(url) from log limit 100
  • 获取0行到第999行的结果,共计1000行:

    1
    * | select distinct(url) from log limit 0,1000
  • 获取第1000行到第1999行的结果,共计1000行:

    1
    * | select distinct(url) from log limit 1000,1000

case when语法

case when语法对连续数据进行归类,例如从http_user_agent中提取信息,归类成Androidios两种

1
2
3
4
5
6
7
select case
when http_user_agent like '%android%' then 'andriod' -- case的两个判断语法
when http_user_agent like '%ios%' then 'ios'
else 'unknown' end -- else语句,end
as http_user_agent,
count(1) as pv
group by http_user_agent

计算不同延时区间的分布

1
2
3
4
5
6
7
8
9
select case
when latency < 10 then 's10'
when latency < 100 then 's100'
when latency < 1000 then 's1000'
when latency < 10000 then 's10000'
else 's_large' end
as latency_slot,
count(1) as pv
group by latency_slot

if语法

if语法逻辑上等同于case when语法

1
2
3
4
case
when condition then true_value
[ else false_value]
end
  • if(condition, true_value)

如果conditiontrue,返回true_value,否则返回的是NULL

  • if(condition, true_value, false_value)

如果conditiontrue,返回true_value,否则返回的是false_value

coalesce语法

返回的是多个列的第一个非NULL值

1
coalesce(value1,value2,...)

nullif语法

如果value1value2相等,返回的是NULL;否则返回的是value1

1
nullif(value1,value2)    -- 如果value1和value2相等,返回的是NULL;否则返回的是value1

二进制字符串函数

二进制字符串类型varbinary有别于字符串类型varchar

  • || :连接函数,等同于concat函数
  • to/from_base64
  • to/from_base64url
语句 说明
连接函数 || a || b 结果为ab
length(binary) → bigint 返回二进制的长度。
concat(binary1, …, binaryN) → varbinary 连接二进制字符串,等同于||。
to_base64(binary) → varchar 把二进制字符串转换成base64。
from_base64(string) → varbinary 把base64转换成二进制字符串。
to_base64url(binary) → varchar 转化成url安全的base64。
from_base64url(string) → varbinary 从url安全的base64转化成二进制字符串。
to_hex(binary) → varchar 把二进制字符串转化成十六进制表示。
from_hex(string) → varbinary 从十六进制转化成二进制。
to_big_endian_64(bigint) → varbinary 把数字转化成大端表示的二进制。
from_big_endian_64(binary) → bigint 把大端表示的二进制字符串转化成数字。
md5(binary) → varbinary 计算二进制字符串的md5。
sha1(binary) → varbinary 计算二进制字符串的sha1。
sha256(binary) → varbinary 计算二进制字符串的sha256 hash。
sha512(binary) → varbinary 计算二进制字符串的sha512。
xxhash64(binary) → varbinary 计算二进制字符串的xxhash64。

位运算

语句 说明 示例
bit_count(x, bits) → bigint 统计x的二进制表示中,1的个数。 SELECT bit_count(9, 64); — 2
SELECT bit_count(9, 8); — 2
SELECT bit_count(-7, 64); — 62
SELECT bit_count(-7, 8); — 6
bitwise_and(x, y) → bigint 以二进制的形式求x,y的and的值。 -
bitwise_not(x) → bigint 以二进制的形式求对x的所有位取反。 -
bitwise_or(x, y) → bigint 以二进制形式对x,y求or。 -
bitwise_xor(x, y) → bigint 以二进制形式对x,y求xor。 -

同比和环比函数

比和环比函数用于比较当前区间的计算结果和之前一个指定区间的结果

函数 含义 样例
compare(value, time_window) 表示将当前时段计算出来的value值和time_window计算出来的结果进行比较。value为double或long类型,time_window单位为秒;返回值为数组类型。返回值分别是当前值、time_window之前的值和当前值与之前值的比值。 *|select compare( pv , 86400) from (select count(1) as pv from log)
compare(value, time_window1, time_window2) 表示当前区间分别和time_window1和time_window2之前的区间值进行比较,结果为json数组。其中,各个值的大小必须满足以下规则:[当前值,time_window1之前的值,time_window2之前的值,当前值/time_window1之前的值,当前值/time_window2之前的值]。 * | select compare(pv, 86400, 172800) from ( select count(1) as pv from log)
compare(value, time_window1, time_window2, time_window3) 表示当前区间分别和time_window1和time_window2,time_window3之前的区间值进行比较,结果为json数组。其中,各个值的大小必须满足以下规则:[当前值,time_window1之前的值,time_window2之前的值,time_window3之前的值,当前值/time_window1之前的值,当前值/time_window2之前的值,当前值/time_window3之前的值]。 * | select compare(pv, 86400, 172800,604800) from ( select count(1) as pv from log)
ts_compare(value, time_window) 表示当前区间分别和time_window1time_window2之前的区间值进行比较,结果为json数组。其中,各个值的大小必须遵循以下规则:[当前值,time_window1之前的值,当前值/time_window1之前的值,前一个时间起点的unix时间戳]。用于时序函数比较,需要在SQL中对时间列进行GROUP BY。 例如,* | select t, ts_compare(pv, 86400 ) as d from(select date_trunc('minute',__time__ ) as t, count(1) as pv from log group by t order by t ) group by t表示将当前时间段每分钟的计算结果和上一个时间段每分钟的计算结果进行比较。结果为:d:[1251.0,1264.0, 0.9897151898734177, 1539843780.0,1539757380.0]t:2018-10-19 14:23:00.000

demo-1

计算当前1小时和昨天同一个时间段的PV比例

笔记:PV(PageView) 页面点击量,每次刷新就算一次浏览,多次打开同一页面会累加

开始时间为2020-03-25 14:00:00;结束时间为2020-03-25 15:00:00。

1
select compare(pv, 86400) from (select count(1) as pv from log)   -- 86400表示当前时间段减去86400秒

假设结果为:

1
[9.0,19.0,0.47368421052631579]

其中:

  • 9:03-25的14:00:00到15:00:00的PV值
  • 19:03-24的14:00到03-25的14:00的PV值
  • 0.47368421052631579:表示当前时间段与之前时间段的比值

将数组展开成3列的写法为:

1
2
3
4
select diff[1], diff[2], diff[3]
from select(compare(pv, 86400) as diff
from (select count(1) as pv
from log))

比较函数和运算符

比较运算判断参数的大小,可以适用于任何可比类型,例如:int、bigint、double、text

比较运算符

当用比较运算符比较两个值得时候,如果逻辑成立,则表示为True,否则返回False

运算符 含义
< 小于
> 大于
<= 小于或等于
>= 大于或等于
= 等于
<> 不等于
!= 不等于

范围运算符 BETWEEN

between用于判断一个参数的值是否在另外两个参数之间,范围为闭区间。

  • 如果逻辑成立,则返回true;否则返回false。

    示例:SELECT 3 BETWEEN 2 AND 6;逻辑成立,返回true。

    以上样例等同于SELECT 3 >= 2 AND 3 <= 6;

  • BETWEEN可以跟在not之后,用于相反逻辑的判断。

    示例:SELECT 3 NOT BETWEEN 2 AND 6;,逻辑不成立,返回false。

    以上样例等同于SELECT 3 < 2 OR 3 > 6;

  • 如果三个参数中任何一个包含Null,则返回的结果为Null。

IS NULL 和 IS NOT NULL

用于判断参数是否为NULL

GREATEST 和 LEAST

用于获取多列中的最大值或者最小值

1
select greatest(1,3,4)   -- 返回的是4

比较判断:all、any、some

比较判断用于判断参数是否满足条件

  • all:用于判断参数是否满足条件
  • any:用于判断是否满足条件之一
  • some:判断参数是否满足条件之一,同any的用法相同

三者必须紧跟在比较运算符之后

表达式 含义
A = ALL (…) A等于所有的值时,结果才是true。
A <> ALL (…) A不等于所有的值时,结果才是true。
A < ALL (…) A小于所有的值时,结果才是true。
A = ANY (…) A等于任何一个值时,结果就为true,等同于 A IN (…)。
A <> ANY (…) A不等于任何一个值时,结果为true。
A < ANY (…) A小于其中最大值时,结果为true。

看几个例子

1
2
3
select 'hello' = any (values 'hello', 'world')    -- true,只要满足一个
select 21 < all (values 19,20,21) -- false,需要全部满足
select 42 >= some(select 41 union all select 42 union all select 43); -- true

Lambda表达式

lambda匿名函数的基本形式为->

1
2
3
4
5
6
7
8
x -> x + 1
(x, y) -> x + y
x -> regexp_like(x, 'a+')
x -> x[1] / x[2]
x -> IF(x > 0, x, -x)
x -> COALESCE(x, 0)
x -> CAST(x AS JSON)
x -> x + TRY(1 / 0)

filter

基本格式:filter(array<T>, function<T,boolean) --->array<T>

1
2
3
select filter (array [], x -> true);   -- []
select filter (array [5, -6, null, 7], x -> x >0); --[5,7]
select filter (array [5,null,7,null], x -> x is not null); -- [5,7]

map_filter

map中过滤数据,只获取满足function且返回true元素对

基本语法格式:map_filter(map<K, V>, function<K, V, boolean>) → MAP<K,V>

1
2
3
SELECT map_filter(MAP(ARRAY[], ARRAY[]), (k, v) -> true); -- {}
SELECT map_filter(MAP(ARRAY[10, 20, 30], ARRAY['a', NULL, 'c']), (k, v) -> v IS NOT NULL); -- {10 -> a, 30 -> c}
SELECT map_filter(MAP(ARRAY['k1', 'k2', 'k3'], ARRAY[20, 3, 15]), (k, v) -> v > 10); -- {k1 -> 20, k3 -> 15}

reduce

基本语法格式为:reduce(array<T>, initialState S, inputFunction<S, T, S>, outputFunction<S, R>) → R

详细步骤为

  1. 初始状态S
  2. 遍历每个元素T
  3. 计算inputFunction(S,T),生成新状态S
  4. 重复步骤2~步骤3,直到最后一个元素被遍历以及生成新状态
  5. 利用最终状态S,获取最终输出结果R
1
2
3
4
select reduce(array [], (s, x) -> s+x, s -> s);   -- 0
select reduce(array [5,20,50], (s, x) -> s+x, s -> s); -- 75
select reduce(array [5,20,null,50], (s, x) -> s+x, s -> s); -- null,任何数加上NULL都是NULL
select reduce(array [5,20,null,50], (s, x) -> s + coalesce(x,0), s -> s); -- 75; coalesce返回的是多个列的第一个非NULL值

transform

基本语法:transform(array<T>, function<T, U>) → ARRAY<U>

对数组中的每个元素,一次调用function,生成新的结果U

1
2
3
select transform(array [], x -> x+1);   --[]
select transform(array [5,6], x -> x+1); -- [6,7]
select transform(array [5,null,6], x -> coalesce(x,0) + 1); -- [6,1,7]

zip_with

基本语法格式:zip_with(array<T>, array<U>, function<T, U, R>) → array<R>

将两个array合并,根据元素T、U,通过函数生成新的array中的元素R

1
2
3
4
5
SELECT zip_with(ARRAY[1, 3, 5], ARRAY['a', 'b', 'c'], (x, y) -> (y, x)); --调换前后两个数组的元素位置,生成新的数组:[['a', 1], ['b', 3],['c', 5]]

SELECT zip_with(ARRAY[1, 2], ARRAY[3, 4], (x, y) -> x + y); -- 对应位置上的元素相加,结果[4, 6]

SELECT zip_with(ARRAY['a', 'b', 'c'], ARRAY['d', 'e', 'f'], (x, y) -> concat(x, y)); -- 把前后两个数组的元素拼接,生成新的字符串:['ad', 'be', 'cf']

逻辑函数

运算符

运算符 描述 样例
AND 只有左右运算数都是true时,结果才为true a AND b
OR 左右运算数任一个为true,结果为true a OR b
NOT 右侧运算数为false时,结果才为true NOT a

NULL参与逻辑运算符

重点标记的一种情况

a b a AND b a OR b
TRUE TRUE TRUE TRUE
TRUE FALSE FALSE TRUE
TRUE NULL NULL TRUE
FALSE TRUE FALSE TRUE
FALSE FALSE FALSE FALSE
FALSE NULL FALSE NULL
NULL TRUE NULL TRUE
NULL FALSE FALSE NULL
NULL NULL NULL NULL

join

SQL中常用的4个join用法

  • inner join
  • left (outer) join
  • right (outer) join
  • full outer join

牢记此图

牢记此图

牢记此图!

img

以下面的两个表格为例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mysql> SELECT * FROM Table_A ORDER BY PK ASC;
+----+---------+
| PK | Value |
+----+---------+
| 1 | both ab |
| 2 | only a |
+----+---------+
2 rows in set (0.00 sec)

mysql> SELECT * from Table_B ORDER BY PK ASC;
+----+---------+
| PK | Value |
+----+---------+
| 1 | both ab |
| 3 | only b |
+----+---------+
2 rows in set (0.00 sec)

inner join

内连接,将左右两个表中能够关联的数据连接起来,并返回出结果;PK为公共字段

必须要有共同的字段!!!

1
2
3
4
5
SELECT A.PK AS A_PK, B.PK AS B_PK,
A.Value AS A_Value, B.Value AS B_Value
FROM Table_A A
INNER JOIN Table_B B
ON A.PK = B.PK;

left (outer) join

左连接,返回左边表的全部记录,不管右表中有没有关联的数据。在右表中找到的关联数据列一并返回

1
2
3
4
5
select A.PK as A_PK,B.PK as B_PK,   -- 字段取别名
A.Value as A_Value, B.Value as B_Value
From Table_A A -- 表取别名
left join Table_B B
on A.PK = B.PK;

right (outer) join

右连接,返回右边表的全部记录,不管左表中有没有关联的数据。在左表中找到的关联数据列一并返回

1
2
3
4
5
select A.PK as A_PK,B.PK as B_PK,   -- 字段取别名
A.Value as A_Value, B.Value as B_Value
From Table_A A -- 表取别名
right join Table_B B
on A.PK = B.PK;

full (outer) join

常被称作外连接,全连接。外连接查询能返回左右表里的所有记录,其中左右表里能关联起来的记录被连接后返回。

mysql中目前没有full join功能

unnest语法

背景

在复杂的业务场景下,日志数据的某一列可能会是较为复杂的格式,例如数组(array)、对象(map)、JSON等格式。对这种特殊格式的日志字段进行查询分析,可以使用unnest语法。

语法结构

unnest接收的是array或者map类型

如果输入的是字符串类型,要先转成json类型,再转化成array类型或者map类型,转化格式:

1
cast(json_parse(array_column) as array(biginit))
语法 说明
unnest( array) as table_alias(column_name) 表示把array类型展开成多行,行的名称column_name
unnest(map) as table(key_name, value_name) 表示把map类型展开成多行,key的名称为key_name,value的名称为value_name

遍历数组的每个元素

  1. 展开数组
1
2
select array_column, a from log,  -- 展开每个元素
unnest(cast(json_parse(array_column) as array(bigint))) as t(a) -- 以t来命名新表,使用a来引用展开后的列
  1. 数组求和
1
2
select sum(a) from log,   -- 求和
unnest(cast(json_parse(array_column) as array(bigint))) as t(a)
  1. 利用 group by 进行分组
1
2
3
select a, count(1) from log,
unnest(cast(json_parse(array_num) as array(bigint))) as t(a)
group by a

遍历map

  1. 遍历map中的元素
1
2
select map_column,a,b from log,
unnest(cast(json_parse(map_column) as map(varchar, bigint))) as t(a,b)
  1. 按照map的key进行统计
1
2
3
select key, sum(value) from log,
unnest(cast(json_parse(map_column) as map(varchar, bigint))) as t(key, value)
group by key;

格式化显示histogram,numeric_histogram

histogram

histogram函数类似于 count group by 语法,其结果通常是一连串的json数据

1
2
select key, value from (select histogram(method) as his from log),
unnest(his) as t(key,value)
numeric_histogram

numeric_histogram语法是将数值列分配到多个桶中去,相当于是对数值列进行group by

1
2
select key,value from (select numeric_histogram(10, Latency) as his from log),
unnest(his) as t(key,value)

电话号码函数

电话号码函数提供对中国内地区域电话号码的归属地查询功能

函数列表

  • mobile_province:省份
  • mobile_city:城市
  • mobile_carrier:运营商
函数名 含义 样例
mobile_province 查看电话号码所属省份,需要传入电话的数字形式。字符串参数可以使用try_cast进行转换。 * | select mobile_province(12345678)``* \| select mobile_province(try_cast('12345678' as bigint) )
mobile_city 查看电话号码所属城市,需要传入电话的数字形式。字符串参数可以使用try_cast进行转换。 * | select mobile_city(12345678)``* \| select mobile_city(try_cast('12345678' as bigint) )
mobile_carrier 查看电话号码所属运营商,需要传入电话的数字形式。字符串参数可以使用try_cast进行转换。 * | select mobile_carrier(12345678)``* \| select mobile_carrier(try_cast('12345678' as bigint) )

demo

1
2
3
4
5
6
7
select mobile_city(try_cast("mobile" as bigint)) as "城市",   -- try_cast将字符串转成数值型
mobile_province(try_cast("mobile" as bigint)) asd "省份",
count(1) as "请求次数"
group by "省份", "城市"
order by "请求次数" desc
limit 1000
)

本文标题:SQL内置函数手册

发布时间:2020年04月24日 - 19:04

原始链接:http://www.renpeter.cn/2020/04/24/SQL%E5%86%85%E7%BD%AE%E5%87%BD%E6%95%B0%E6%89%8B%E5%86%8C.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

Coffee or Tea