文章目录
- [第六章 函数](#第六章 函数)
第六章 函数
1.函数介绍
GreenPlum会将常用的逻辑封装成函数给用户进行使用,类似于Java中方法。好处就是不用重复写逻辑,直接用即可。所以为了在使用更快速便捷的入手,需要了解下GP数据库提供了哪些内置函数,然后根据需要选择对应的函数进行使用。
2.单行函数
单行函数的特点就是一进一出,输入一行,输出一行。
2.1 算术运算符
运算符 | 描述 |
---|---|
A+B | A和B 相加 |
A-B | A减去B |
A*B | A和B 相乘 |
A/B | A除以B |
A%B | A对B取余 |
A&B | A和B按位取与 |
A|B | A和B按位取或 |
A^B | A和B按位取异或 |
~A | A按位取反 |
2.2 数值函数
函数 | 返回类型 | 描述 | 例子 | 结果 |
---|---|---|---|---|
abs(x) | (与x相同) | 绝对值 | - | - |
ceil(dp或numeric)\ceiling | (与输入相同) | 不小于参数的最小整数 | - | - |
exp(dp或numeric) | (与输入相同) | 自然指数 | - | - |
ln(dp或numeric) | (与输入相同) | 自然对数 | - | - |
log(dp或numeric) | (与输入相同) | 以10 为底的对数 | - | - |
log(b numeric,x numeric) | numeric | 以b为底的对数 | - | - |
mod(y,x) | (与参数类型相同) | y/x的余数 | - | - |
pi() | dp | π | - | - |
power(a numeric,b numeric) | numeric | a的b次幂 | - | - |
radians(dp) | dp | 把角度转为弧度 | - | - |
random() | dp | 0~1之间的随机数 | ||
floor(dp或numeric) | (与输入相同) | 不大于参数的最大整数 | - | - |
round(v numeric,s int) | numeric | 圆整为s位小数 | round(42.4382,2) | 42.44 |
sign(dp或numeric) | (与输入相同) | 参数的符号(-1,0,+1) | sing(-8,4) | -1 |
sqrt(dp或numeric) | (与输入相同) | 平方根 | - | - |
cbrt(dp) | dp | 立方根 | - | - |
trunc(v numeric,s int) | numeric | 截断为s位小数 | - | - |
sh
# 1.random随机0-1之间的数值
zxy=# select random();
random
------------------
0.89662363845855
(1 row)
# 2.ceil向上取整
zxy=# select ceil(3.14);
ceil
------
4
(1 row)
# 3.floor向下取整
zxy=# select floor(3.14);
floor
-------
3
(1 row)
# 4.保留两位小数
zxy=# select round(3.1415926,2);
round
-------
3.14
(1 row)
2.3 字符串函数
函数 | 返回类型 | 描述 | 例子 | 结果 |
---|---|---|---|---|
string||string | text | 字符串连接 | ||
length(string) | int | string中字符的数目 | length('jose') | 4 |
position(substring in string) | int | 指定的子字符串的位置 | position('om'in'Tomas') | 3 |
substring(string[from int][for int]) | text | 抽取子字符串 | substring('Thomas'from 2 for 3) | hom |
trim([leading|trailing|both][characters]from string) | text | 从字符串string的开头/结尾/两边删除只包含characters中字符(默认是空白)的最长的字符串 | trim(both 'x' from 'xTomxx') | Tom |
lower(string) | text | 把字符串转化为小写 | ||
upper(string) | text | 把字符串转化为大写 | ||
overlay(string placing string from int [for int]) | text | 替换子字符串 | overlay('Txxxxas' placing 'hom' from 2 for 4) | Thomas |
replace(string text,from text,to text) | text | 把字符串string中出现的所有子字符串from替换成子字符串to | replace('abcdefabcdef','cd,'XX') | abXXefabXXef |
split_part(string text, delimiter text,filed int) | text | 根据delimiter分隔string返回生成的第field个子字符串(1开始) | split_part('abc|def|ghi','|',2) | def |
concat_ws(string text,string text...) | text | 使用分隔符A拼接多个字符串,或者一个数组的所有元素。 | concat_ws('-','a','b','c') | a-b-c |
sh
# 1.拼接字符串
zxy=# select 'a'||'b';
?column?
----------
ab
(1 row)
# 2.使用连接符连接字符串
zxy=# select concat_ws('-','a','b','c');
concat_ws
-----------
a-b-c
(1 row)
# 3.根据指定符号分割字符串
zxy=# select split_part('a-b-c','-',1);
split_part
------------
a
(1 row)
2.4 时间函数
使用interval类型可以直接对事件类型进行计算,用来计算时间的加减
函数 | 返回类型 | 描述 | 例子 | 结果 |
---|---|---|---|---|
age(timestamp,timestamp) | interval | 减去参数后的"符号化"结果 | age(timestamp'2001-04-10',timestamp'1957-06-13) | 43 years 9 mons 27 das |
age(timestam) | interval | 从current_date减去参数中的日期 | age(timestam'1957-06-13) | - |
current_date | date | 当前的日期 | - | - |
current_time | time with time zone | 当日时间 | - | - |
current_timestamp | timestamp with time zone | 当前事务开始时的事件戳 | - | - |
date_part(text,timestamp) | double precision | 获取子域(等效于extract) | date_part('hour',timestamp'2001-02-16 20:38:40) | 20 |
date_trunc(text,timestamp) | timestamp | 截断成指定的精度 | date_trunc('hour',timestamp '2001-02-16 20:38:40') | 2001/2/16 20:00 |
extract(field from timestamp) | double precision | 获取子域 | (同date_part) | (同date_part) |
now() | timestampe with time zone | 当前事务开始的时间戳 | - |
sh
# 1.求日期相差的年龄
zxy=# select age('2002-01-01'::timestamp,'2000-02-13'::timestamp);
age
------------------------
1 year 10 mons 17 days
(1 row)
# 2.从日期中提取年
zxy=# select extract(year from current_date);
date_part
-----------
2024
(1 row)
# 3.从日期中提取年
zxy=# select date_part('year',current_date);
date_part
-----------
2024
(1 row)
# 4.interval日期相加
zxy=# select '2000-01-01'::timestamp + interval '1 days';
?column?
---------------------
2000-01-02 00:00:00
(1 row)
2.5 流程控制函数
case when:条件判断函数
case when a then b [when c then d]* [else e] end
如果a为true,则返回b;如果c为true,则返回d;否则返回e;
sh
# 1.查看emp表
zxy=# select * from ods.emp;
empno | ename | job | sal | deptno
-------+--------+------+------+--------
7521 | 王五 | 行政 | 1250 | 10
7566 | 赵六 | 销售 | 2975 | 40
7844 | 小明 | 销售 | 1500 | 40
7900 | 小元 | 讲师 | 950 | 30
7369 | 张三 | 研发 | 800 | 30
7499 | 李四 | 财务 | 1600 | 20
7698 | 马八 | 研发 | 2850 | 30
7902 | 小海 | 行政 | 3000 | 10
7934 | 小红明 | 讲师 | 1300 | 30
7782 | 金九 | | 2450 | 30
7654 | 侯七 | 研发 | 1250 | 30
7876 | 小李 | 行政 | 1100 | 10
7788 | 银十 | 行政 | 3000 | 10
7839 | 小芳 | 销售 | 5000 | 40
7999 | 小八 | 行政 | 4000 | 10
(14 rows)
# 2.case when匹配对应deptno
zxy=# select empno,ename,job,sal,
zxy-# case deptno when 10 then '行政部'
zxy-# when 20 then '财务部'
zxy-# when 30 then '教学部'
zxy-# when 40 then '销售部'
zxy-# end as dname
zxy-# from ods.emp;
empno | ename | job | sal | dname
-------+--------+------+------+--------
7788 | 银十 | 行政 | 3000 | 行政部
7839 | 小芳 | 销售 | 5000 | 销售部
7369 | 张三 | 研发 | 800 | 教学部
7499 | 李四 | 财务 | 1600 | 财务部
7698 | 马八 | 研发 | 2850 | 教学部
7902 | 小海 | 行政 | 3000 | 行政部
7934 | 小红明 | 讲师 | 1300 | 教学部
7782 | 金九 | | 2450 | 教学部
7521 | 王五 | 行政 | 1250 | 行政部
7566 | 赵六 | 销售 | 2975 | 销售部
7844 | 小明 | 销售 | 1500 | 销售部
7900 | 小元 | 讲师 | 950 | 教学部
7654 | 侯七 | 研发 | 1250 | 教学部
7876 | 小李 | 行政 | 1100 | 行政部
7999 | 小八 | 行政 | 4000 | 行政部
(14 rows)
3.行列转换函数
3.1 行转列函数
string_agg(column,parten)
sh
zxy=# select string_agg(ename,',') from ods.emp;
string_agg
-------------------------------------------------------------------------
侯七,小李,银十,小芳,张三,李四,马八,小海,小红明,金九,王五,赵六,小明,小元,小八
(1 row)
3.2 列转行函数
regexp_split_to_table(column,parten)
sh
zxy=# select regexp_split_to_table('侯七,小李,银十,小芳,张三,李四,马八,小海,小红明,金九,王五,赵六,小明,小元,小八',',');
regexp_split_to_table
-----------------------
侯七
小李
银十
小芳
张三
李四
马八
小海
小红明
金九
王五
赵六
小明
小元
小八
(14 rows)
4.窗口函数
4.1 概述
窗口函数,能为每行数据划分一个窗口,然后对窗口范围内数据进行计算,最后将计算结果返回给该行数据。
4.2 常用窗口函数
1)聚合函数
-
max:最大值
shzxy=# select empno,ename,job,max(sal) over(partition by job) from ods.emp; empno | ename | job | max -------+--------+------+------ 7521 | 王五 | 行政 | 4000 7788 | 银十 | 行政 | 4000 7902 | 小海 | 行政 | 4000 7876 | 小李 | 行政 | 4000 7999 | 小八 | 行政 | 4000 7934 | 小红明 | 讲师 | 1300 7900 | 小元 | 讲师 | 1300 7782 | 金九 | | 2450 7654 | 侯七 | 研发 | 2850 7698 | 马八 | 研发 | 2850 7369 | 张三 | 研发 | 2850 7844 | 小明 | 销售 | 5000 7566 | 赵六 | 销售 | 5000 7839 | 小芳 | 销售 | 5000 7499 | 李四 | 财务 | 1600 (14 rows)
-
min:最小值
shzxy=# select empno,ename,job,min(sal) over(partition by job) from ods.emp; empno | ename | job | min -------+--------+------+------ 7499 | 李四 | 财务 | 1600 7369 | 张三 | 研发 | 800 7698 | 马八 | 研发 | 800 7654 | 侯七 | 研发 | 800 7844 | 小明 | 销售 | 1500 7566 | 赵六 | 销售 | 1500 7839 | 小芳 | 销售 | 1500 7902 | 小海 | 行政 | 1100 7521 | 王五 | 行政 | 1100 7876 | 小李 | 行政 | 1100 7788 | 银十 | 行政 | 1100 7999 | 小八 | 行政 | 1100 7934 | 小红明 | 讲师 | 950 7900 | 小元 | 讲师 | 950 7782 | 金九 | | 2450 (14 rows)
-
sum:求和
shzxy=# select empno,ename,job,sum(sal) over(partition by job) from ods.emp; empno | ename | job | sum -------+--------+------+------- 7876 | 小李 | 行政 | 12350 7999 | 小八 | 行政 | 12350 7521 | 王五 | 行政 | 12350 7902 | 小海 | 行政 | 12350 7788 | 银十 | 行政 | 12350 7900 | 小元 | 讲师 | 2250 7934 | 小红明 | 讲师 | 2250 7782 | 金九 | | 2450 7499 | 李四 | 财务 | 1600 7698 | 马八 | 研发 | 4900 7369 | 张三 | 研发 | 4900 7654 | 侯七 | 研发 | 4900 7839 | 小芳 | 销售 | 9475 7844 | 小明 | 销售 | 9475 7566 | 赵六 | 销售 | 9475 (15 rows)
-
avg:平均值
shzxy=# select empno,ename,job,avg(sal) over(partition by job) from ods.emp; empno | ename | job | avg -------+--------+------+------------------ 7698 | 马八 | 研发 | 1633.33333333333 7369 | 张三 | 研发 | 1633.33333333333 7654 | 侯七 | 研发 | 1633.33333333333 7844 | 小明 | 销售 | 3158.33333333333 7566 | 赵六 | 销售 | 3158.33333333333 7839 | 小芳 | 销售 | 3158.33333333333 7788 | 银十 | 行政 | 2470 7902 | 小海 | 行政 | 2470 7999 | 小八 | 行政 | 2470 7876 | 小李 | 行政 | 2470 7521 | 王五 | 行政 | 2470 7934 | 小红明 | 讲师 | 1125 7900 | 小元 | 讲师 | 1125 7782 | 金九 | | 2450 7499 | 李四 | 财务 | 1600 (15 rows)
-
count:计数
shzxy=# select empno,ename,job,count(sal) over(partition by job) from ods.emp; empno | ename | job | count -------+--------+------+------- 7499 | 李四 | 财务 | 1 7521 | 王五 | 行政 | 5 7788 | 银十 | 行政 | 5 7902 | 小海 | 行政 | 5 7999 | 小八 | 行政 | 5 7876 | 小李 | 行政 | 5 7900 | 小元 | 讲师 | 2 7934 | 小红明 | 讲师 | 2 7782 | 金九 | | 1 7698 | 马八 | 研发 | 3 7369 | 张三 | 研发 | 3 7654 | 侯七 | 研发 | 3 7839 | 小芳 | 销售 | 3 7844 | 小明 | 销售 | 3 7566 | 赵六 | 销售 | 3 (15 rows)
2)跨行取值函数
-
lag和lead
lag(column,offset,default)获取当前行的上某行,某个字段的值
lead(column,offset,default)获取当前行的下某行,某个字段的值
- column是指定字段
- offset是指定偏移量
- default指定找不到符合条件后的默认值
shzxy=# select empno,ename,job,lag(empno,1,'1') over(partition by job order by empno) lagno,lead(empno,1,'9999') over(partition by job order by empno) leadno from ods.emp; empno | ename | job | lagno | leadno -------+--------+------+-------+-------- 7521 | 王五 | 行政 | 1 | 7788 7788 | 银十 | 行政 | 7521 | 7876 7876 | 小李 | 行政 | 7788 | 7902 7902 | 小海 | 行政 | 7876 | 7999 7999 | 小八 | 行政 | 7902 | 9999 7900 | 小元 | 讲师 | 1 | 7934 7934 | 小红明 | 讲师 | 7900 | 9999 7782 | 金九 | | 1 | 9999 7499 | 李四 | 财务 | 1 | 9999 7369 | 张三 | 研发 | 1 | 7654 7654 | 侯七 | 研发 | 7369 | 7698 7698 | 马八 | 研发 | 7654 | 9999 7566 | 赵六 | 销售 | 1 | 7839 7839 | 小芳 | 销售 | 7566 | 7844 7844 | 小明 | 销售 | 7839 | 9999 (15 rows)
3)排名函数
-
row_number
连续不重复
shzxy=# select job,ename,sal,row_number() over(partition by job order by sal) from ods.emp where job = '行政'; job | ename | sal | row_number ------+-------+------+------------ 行政 | 小李 | 1100 | 1 行政 | 王五 | 1250 | 2 行政 | 小海 | 3000 | 3 行政 | 银十 | 3000 | 4 行政 | 小八 | 4000 | 5 (5 rows)
-
rank
不连续不重复
shzxy=# select job,ename,sal,rank() over(partition by job order by sal) from ods.emp where job = '行政'; job | ename | sal | rank ------+-------+------+------ 行政 | 小李 | 1100 | 1 行政 | 王五 | 1250 | 2 行政 | 银十 | 3000 | 3 行政 | 小海 | 3000 | 3 行政 | 小八 | 4000 | 5 (5 rows)
-
dense_rank
连续重复
shzxy=# select job,ename,sal,dense_rank() over(partition by job order by sal) from ods.emp where job = '行政'; job | ename | sal | dense_rank ------+-------+------+------------ 行政 | 小李 | 1100 | 1 行政 | 王五 | 1250 | 2 行政 | 小海 | 3000 | 3 行政 | 银十 | 3000 | 3 行政 | 小八 | 4000 | 4 (5 rows)
5.其他函数
1)序列号生成函数-generate_series(x,y,t)
生成多行数据从x到y,步长为t,默认步长是1
sh
zxy=# select generate_series(1,10,1);
generate_series
-----------------
1
2
3
4
5
6
7
8
9
10
(10 rows)