十.MySQL函数

1.概述

在MySQL中,为了提高代码重用性和隐藏实现细节,MySQL提供了很多函数。函数可以理解为别人封装好的模板代码。

2.分类

(1).聚合函数

(2).数学函数

(3).字符串函数

(4).日期函数

(5).控制流函数

(6).窗口函数

3.MySQL函数-聚合函数

(1).概述

在MySQL中,聚合函数主要由: count, sum, min, max, avg group_concat()

group_concat函数作用实现行合并

group_concat函数首先根据group by指定的列进行分组,并且用分隔符分隔,将同一个分组中的值连接起来,返回一个字符串结果.

(2).格式

group_concat([distinct] 字段名 [order by 排序字段 asc/desc] [separator '分隔符'])

说明:
[1].使用distinct可以排除重复值

​ [2].如果需要对结果中的值进行排序,可以使用order by子句

​ [3].separator是一个字符串值,默认为逗号

(3).示例

-- 创建表
create table emp(
  emp_id int primary key auto_increment comment '编号',
  emp_name char(20) not null default '' comment '姓名',
  salary decimal(10, 2) not null default 0 comment '工资',
  department char(20) not null default '' comment '部门'  
);

-- 插入数据
insert into emp(emp_name, salary, department) values ('张晶晶', 5000, '财务部');
insert into emp(emp_name, salary, department) values ('王飞飞', 5800, '财务部');
insert into emp(emp_name, salary, department) values ('赵刚', 6200, '财务部');
insert into emp(emp_name, salary, department) values ('刘小贝', 5700, '人事部');
insert into emp(emp_name, salary, department) values ('王大鹏', 6700, '人事部');
insert into emp(emp_name, salary, department) values ('张小斐', 5200, '人事部');
insert into emp(emp_name, salary, department) values ('刘云云', 7500, '销售部');
insert into emp(emp_name, salary, department) values ('刘云鹏', 7200, '销售部');
insert into emp(emp_name, salary, department) values ('刘云鹏', 7800, '销售部');

-- 1.将所有员工的名字合并成一行
select group_concat(emp_name) from emp;

-- 2.指定分隔符合并
select group_concat(emp_name separator ';') from emp;

-- 3.指定排序方式和分隔符
select department, group_concat(emp_name separator ';') from emp group by department;
select department, group_concat(emp_name order by salary separator ';') from emp group by department;

4.MySQL函数-数学函数

(1).分类

函数名描述示例
ABS(x)返回x的绝对值返回-1的绝对值:select ABS(-1); – 返回1
CEIL(X)返回大于或等于x的最小整数select CEIL(1.5); – 返回2
FLOOR(x)返回小于或等于x的最大整数小于或等于1.5的整数:select FLOOR(1.5); – 返回1
GREATEST(expr1, expr2, …)返回列表中的最大值返回以下数字列表中的最大值:select GREATEST(3, 12, 34, 8, 25); – 返回34返回以下字符串列表中的最大值:select GREATEST(‘Geogle’, ‘Runoob’, ‘Apple’); – 返回Runoob
LEAST(expr1, expr2, …)返回列表中的最小值返回以下数字列表中的最小值:select LEAST(3, 12, 34, 8, 25); – 返回3返回以下字符串列表中的最小值:select LEAST(‘Geogle’, ‘Runoob’, ‘Apple’); – 返回Apple
MAX(expression)返回字段expression中的最大值返回数据表Products中字段Price的最大值:select MAX(Price) as LargestPrice from Products
MIN(expression)返回字段expression中的最小值返回数据表Products中字段Price的最小值:select MIN(Price) as LargestPrice from Products
MOD(x, y)返回x除以y以后的余数5除以2的余数:select MOD(5, 2); – 1
PI()返回圆周率(3.141593)select PI(); – 3.141593
POW(x, y)返回x的y次方2的3次方:select POW(2, 3); – 8
RAND()返回0到1的随机数select rand(); – 0.3089158770711309
ROUND(x)返回离x最近的整数(遵循四舍五入)select round(1.23456); – 1
ROUND(x, y)返回指定位数的小数(遵循四舍五入)select round(1.23456, 3); --1.235
TRUNCATE(x, y)返回数值x保留到小数点后y位的值(与ROUND最大的区别是不会进行四舍五入)select TRUNCATE(1.23456, 3) – 1.234

(2).示例

-- abs 求绝对值
select abs(-10); -- 10
select abs(10); -- 10
select abs(表示式或者字段) from-- ceil 向上取整
select CEIL(1.1); -- 2
select CEIL(1.0); -- 1

-- floor 向下取整
select floor(1.1); -- 1
select floor(1.0); -- 1

-- 取列表最大值
select GREATEST(1, 2, 3); -- 3

-- 取列表最小值
select least(1, 2, 3); -- 1

-- 取模
select mod(5, 2); -- 1

-- 乘方
select pow(2, 3); --8

-- 取随机值
select rand(); -- 0.125484 
-- 获取0-100随机数
select floor(rand() * 100); -- 14
 
-- 将小数的四舍五入取整
select round(3.5415) -- 4
-- 对小数的某一位取整
select round(3.5415, 3); -- 3.542

-- 将小数直接截取到指定位数
select truncate(3.1415, 3); -- 3.141

5.MySQL的函数 - 字符串函数

(1).分类

函数描述实例
CHAR_LENGTH(s)返回字符串s的字符数返回字符串RUNOOB的字符数:select CHAR_LENGTH(‘RUNOOB’) as lengOfString; – 6
CHARACTER_LENGTH(s)返回字符串s的字符数返回字符串RUNOOB的字符数:select CHARACTER_LENGTH(‘RUNOOB’) as lengOfString; – 6
CONCAT(s1, s2,…)字符串s1,s2等多个字符串合并为一个字符串合并多个字符串:select CONCAT(‘a’, ‘b’, ‘c’); – abc
CONCAT_WS(x, s1, s2, …)同concat(s1, s2,…)函数,但是每个字符之间要加上x, x可以是分隔符合并多个字符串,并添加分隔符:select CONCAT_WS('', ‘a’, ‘b’, ‘c’); – ab*c
FLELD(s,s1,s2,…)返回第一个字符串在字符串列表(s1, s2, …)中的位置返回字符串abc在列表值中的位置:select FIELD(‘abc’, ‘abc’, ‘bcd’, ‘edf’); – 1
LTRIM(s)去掉字符串s开始处的空格去掉字符串RUNOOB开始处的空格:select LTRIM(’ RUNOOB’); – RUNOOB
MID(s, n, len)从字符串s的n位置截取长度为len的子字符串,同SUBSTRING(s, n, len)从字符串RUNOOB中的第2个位置截取3个字符:select mid(‘runoob’, 2, 3); – uno
POSITION(s1 IN s)从字符串s中获取s1的开始位置返回字符串abc中b的位置:select POSITION(‘b’ in ‘abc’); – 2
REPLACE(s, s1, s2)将字符串s2替代字符串s中的字符串s1将字符串abc中的字符a替换为字符x:select replace(‘abc’, ‘a’, ‘x’); – xbc
REVERSE(s)将字符串s的顺序反过来将字符串abc的顺序反过来select REVERSE(‘abc’); – cba
RIGHT(s, n)返回字符串s的后n个字符返回字符串runoob的后两个字符:SELECT right(‘runoob’, 2); – ob
RTRIM(s)去掉字符串s结尾处的空格去掉字符串aaaaa 的末尾空格:select RTRIM('aaaaa '); – aaaaa
STRCMP(s1, s2)比较字符串s1和s2, 如果s1与s2相等返回0. 如果s1>s2,返回1. 如果s1比较字符串:select STRCMP(‘abc’, ‘abc’); – 0
SUBSTR(s, start, length)从字符串s的start位置截取长度为length的子字符串从字符串RUNOOB中的第2个位置截取3个字符:select substr(‘RUNOOB’, 2, 3); – UNO
SUBSTRING(s, start, length)从字符串s的start位置截取长度为length的子字符串从字符串RUNOOB中的第2个位置截取3个字符:select substring(‘RUNOOB’, 2, 3); – UNO
TRIM(s)去掉字符串s开始和结尾处的空格去掉字符串RUNOOB的首尾空格:select trim(’ RUNOOB '); – RUNOOB
UCASE(s)将字符串转换为大写将字符串runoob转换为大写:select ucase(‘runoob’); – RUNOOB
UPPER(s)将字符串转换为大写将字符串runoob转换为大写:select upper’runoob’); – RUNOOB
LCASE(s)将字符串转换为小写将字符串RUNOOB转换为小写:select ucase(‘RUNOOB’); – runoob
LOWER(s)将字符串转换为小写将字符串RUNOOB转换为小写:select ucase(‘RUNOOB’); – runoob

(2).示例

-- 1.获取字符串字符个数
select char_length('hello'); -- 5
select char_length('你好吗'); -- 3

-- 2.获取字符串字节长度
-- length取长度,返回的单位是字节
select length('hello'); -- 5
select length('你好吗'); -- 9

-- 3.字符串合并
select concat('hello', 'wrold'); -- helloworld
select concat(c1, c2) from tablename;

-- 4.指定分隔符进行字符串合并
select concat_ws('-', 'hello', 'world'); -- hello-world

-- 5.返回字符串在列表中第一次出现的位置
select field('aaa', 'aaa', 'bbb', 'ccc'); -- 1

-- 6.去除字符串空格
-- 去除字符串左边空格
select ltrim('    aaa'); -- aaa
-- 去除字符串右边空格
select rtrim('aaa   '); -- aaa
-- 去除左右边空格
select trim('  aaa  '); -- aaa

-- 7.字符串截取
select mid('helloworld', 2, 3); -- ell

-- 8.获取字符串abc在字符串habcelloabcworld中出现的位置
select position('abc' in 'habcelloabcworld'); -- 2

-- 9.字符串替换
select replace('helloaaaworld', 'aaa', 'bbb'); -- hellobbbworld

-- 10.字符串反转
select reverse('hello'); -- olleh

-- 11.返回字符串的后几个字符
select right('hello', 3); -- llo

-- 12.字符串比较
select strcmp('hello', 'world'); -- -1

-- 13.字符串截取
-- 从第二个字符开始截取,截取三个字符
select substr('hello', 2, 3); -- llo
-- 从第二个字符开始截取,截取三个字符
select substring('hello', 2, 3); -- llo

-- 14.将小写转大写
select ucase('helloworld'); -- HELLOWORLD
select upper('helloworld'); -- HELLOWORLD

-- 15.将大写转成小写
select lcase('HELLOWORLD'); -- helloworld
select lower('HELLOWORLD'); -- helloworld

6.MySQL函数–日期函数

(1).分类

函数名描述实例
UNIX_TIMESTAMP()返回从1970-01-01 00:00:00到当前毫秒数select UNIX_TIMESTAMP(); – 1642986095
UNIX_TIMESTAMP(DATE_STRING)将指定日期转为毫秒值时间戳select UNIX_TIMESTAMP(‘2020-12-14 12:15:14’); – 1607919314
FROM_UNIXTIME(BIGINT UNIXTIME, STRING FORMAT);将毫秒值时间戳转为指定格式日期select FROM_UNIXTIME(1598079966, ‘%Y-%m-%d %H:%i:%s’); – 2020-08-22 15:06:06
CURDATE()返回当前日期select curdate(); – 2022-01-24
CURRENT_DATE()返回当前日期select CURRENT_DATE(); – 2022-01-24
CURRENT_TIME返回当前时间select current_time(); – 12:45:08
CURTIME()返回当前时间select CURTIME(); – 12:46:06
CURRENT_TIMESTAMP()返回当前日期和时间select CURRENT_TIMESTAMP(); – 2022-01-24 12:46:54
DATE()从日期或日期时间表达式中提取日期值select date(‘2020-12-14’); – 2020-12-14
DATEDIFF(d1, d2)计算日期d1>d2之间相隔的天数select DATEDIFF(‘2022-1-1’, ‘2022-2-1’); – -31
TIMEDIFF(time1, time2)计算时间差值select TIMEDIFF(‘13:01:12’, ‘13:02:12’); – -00:01:00
DATE_FORMAT(d, f)按表达式f的要求显示日期dselect date_format(‘2020-12-14 15:24:14’, ‘%Y-%m-%d’); – 2020-12-14
STR_TO_DATE(string, format_mask)按字符串转变为日期select STR_TO_DATE(‘August 10 2020’, ‘%M %d %Y’); – 2020-08-10
DATE_SUB(date, INTERVAL expr type)函数从日期减去指定的时间间隔给定日期减去2天:select DATE_SUB(‘2021-12-14 10:10:10’, INTERVAL 2 DAY); – 2021-12-12 10:10:10
ADDDATE/DATE_ADD(d, INTERVAL expr type)计算起始日期d加上一个时间段后的日期,type值可以是:MICROSECONDSECONDMINUTEHOURDAYWEEKMONTHQUARTERYEARDAY_MINUTEDAY_HOURYEAR_MONTHselect date_add(‘2017-06-15’, INTERVAL 10 DAY); – 2017-06-25select date_add(‘2017-06-15 09:34:21’, INTERVAL 15 MINUTE); – 2017-06-15 09:49:21select date_add(‘2017-06-15 09:34:21’, INTERVAL -3 HOUR); – 2017-06-15 06:34:21
EXTRACT(type FROM d)从日期d中获取指定的值,type指定返回的值。type可取值为:MICROSECONDSECONDMINUTEHOUR…select EXTRACT(MINUTE from ‘2021-12-14 15:16:17’); – 16
LAST_DAY(d)返回给给定日期的那一月份的最后一天select LAST_DAY(‘2022-02-10’); – 2022-02-28
MAKEDATE(year, day-of-year)基于给定参数年份year和所在年中的天数序号 day-of-year返回一个日期select MAKEDATE(2017, 32); – 2017-02-01
YEAR(d)返回年份select year(‘2017-06-15 12:12:12’); – 2017
MONTH(d)返回日期d中的月份值,1到12select month(‘2017-06-15 12:12:12’); – 6
DAY(d)返回日期值d的日期部分select day(‘2017-06-15 12:12:12’); – 15
HOUR(t)返回t的小时值select hour(‘14:12:16’); – 14
MINUTE(t)返回t的分钟值select minute(‘14:12:16’); – 12
SECOND(t)返回t的分秒值select second(‘14:12:16’); – 16
QUARTER(d)返回日期d是第几季节,返回1到4select QUARTER(‘2017-06-15’); – 2
MONTHNAME(d)返回日期当中的月份名称, 如Novemberselect MONTHNAME(‘2021-02-13 14:15:16’); – February
MONTH(d)返回日期d中的月份值,1到12select MONTH(‘2021-02-13 14:15:16’); – 2
DAYNAME(d)返回日期d是星期几,如Monday, Tuesdaysselect DAYNAME(‘2021-02-13 14:15:16’); – Saturday
DAYOFMONTH(d)计算日期d是本月的第几天select DAYOFMONTH(‘2021-02-13 14:15:16’); – 13
DAYOFWEEK(d)日期d今天是星际几,1星期日,2星期一,以此类推select DAYOFWEEK(‘2021-02-13 14:15:16’); – 7
DAYOFYEAR(d)计算日期d是本年的第几天select DAYOFYEAR(‘2021-02-13 14:15:16’); – 44
WEEK(d)计算日期d是本年的第几个星期,范围是0~53select week(‘2020-11-12 13:45:20’); – 45
WEEKDAY(d)日期d是星期几,0表示星期一,1表示星期二select weekday(‘2017-06-15’); – 3
WEEKOFYEAR(d)计算日期d是本年的第几个星期,范围是0到53select WEEKOFYEAR(‘2017-06-15’); – 24
YEARWEEK(date, mode)返回年份及第几周,mode中0表示周日,1表示周一。以此类推select YEARWEEK(‘2017-06-15’); – 201724
NOW()返回当前日期和时间

其中FROM_UNXITIME格式:

格式描述
%a编写星期名
%b编写月名
%c月,数值
%d月的天,数值(00-31)
%e月的天, 数值(0-31)
%f微秒
%H小时(00 - 23)
%h小时(01 - 12)
%I小时(01-12)
%i分钟, 数值(00 - 59)
%j年的天(001 - 366)
%k小时(0 - 23)
%l小时(1-12)
%M月名
%m月,数值(00 - 12)
%pAM 或 PM
%r时间,12-小时(hh:mm:ss AM 或 PM)
%S秒(00 - 59)
%s秒(00 - 59)
%T时间, 24-小时(hh:mm:ss)
%U周(00-53) 星期日是一周的第一天
%u周(00-53)星期一是一周的第一天
%V周(01-53)星期日是一周的第一天,与%X使用
%v周(01-53)星期一是一周的第一天,与%x使用
%W星期名
%w周的天(0-星期日, 6-星期六)
%X年,其中的星期日是周的第一天,4位,与%V使用
%x年,其中的星期一是周的第一天,4位,与%v使用
%Y年,4位
%y年,2位

(2).示例

-- 1.获取时间戳(毫秒值)
select UNIX_TIMESTAMP(); -- 1642986095

-- 2.将一个日期字符串转为毫秒值
select UNIX_TIMESTAMP('2021-12-11 08:08:08'); -- 1639181288

-- 3.将时间戳毫秒值转为指定格式的日期
select FROM_UNIXTIME(1598079966, '%Y-%m-%d %H:%i:%s'); -- 2020-08-22 15:06:06

-- 4.获取当前的年月日
select CURDATE(); -- 2022-01-24
select CURRENT_DATE(); -- 2022-01-24

-- 5.获取当前的时分秒
SELECT current_time(); -- 12:52:14
select curtime(); -- 12:12:14

-- 6.获取年月日和时分秒
SELECT CURRENT_TIMESTAMP(); -- 2022-01-24 12:53:59

-- 7.从日期字符串中获取年月日
select date('2022-01-01 12:16:00'); -- 2022-01-01

-- 8.获取日期之间的差值
select DATEDIFF('2022-1-1', '2022-2-1'); -- -31
select DATEDIFF(CURRENT_DATE(), '2008-08-08'); -- 4917

-- 9.获取时间的差值(秒级)
select TIMEDIFF('13:01:12', '13:02:12'); -- -00:01:00

-- 10.日期格式化
select date_format('2020-12-14 15:24:14', '%Y-%m-%d'); -- 2020-12-14
select date_format('2020-12-16 15:26:16', '%Y-%m-%d'); -- 2020-12-16

-- 11.将字符串转为日期
select STR_TO_DATE('August 10 2020', '%M %d %Y'); -- 2020-08-10

-- 12.将日期进行减法
-- 日期向前跳
select DATE_SUB('2021-12-14 10:10:10', INTERVAL 2 DAY); -- 2021-12-12 10:10:10

-- 13.将日期进行加法
-- 日期向后跳
select date_add('2017-06-15 09:34:21', INTERVAL -3 HOUR); -- 2017-06-15 06:34:21

-- 14.从日期中获取小时
select EXTRACT(hour from '2021-12-14 15:16:17'); -- 15

-- 15.获取给定日期所在月的最后一天
select last_day('2022-01-14'); -- 2022-01-31

-- 16.获取指定年份和天数的日期
select makedate('2021', 32); -- '2021-02-01'

-- 17.根据日期获取年月日,时分秒
select year('2021-02-13 14:15:16'); -- 2021
select month('2021-02-13 14:15:16'); -- 02
select minute('2021-02-13 14:15:16'); -- 15
select quarter('2021-02-13 14:15:16'); -- 1

--18.根据日期获取信息
-- 获取月份的英文
select MONTHNAME('2021-02-13 14:15:16'); -- February
-- 获取周几
select DAYNAME('2021-02-13 14:15:16'); -- Saturday
-- 获取当月的第几天
select DAYOFMONTH('2021-02-13 14:15:16'); -- 13
-- 获取星期几 1:周日 2:周一
select DAYOFWEEK('2021-02-13 14:15:16'); -- 7
-- 获取一年的第几天
select DAYOFYEAR('2021-02-13 14:15:16'); -- 44

7.MySQL函数 - 控制流程函数

(1).if逻辑判断语句

[1].分类

格式解释示例
IF(expr, v1, v2)如果表达式expr成立,返回结果v1;否则,返回结果v2select if(1 > 0, ‘正确’, ‘错误’); – 正确
IFNULL(v1, v2)如果v1的值不为NULL, 则返回v1, 否则返回v2select IFNULL(null, ‘hello world’); – hello world
ISNULL(expression)判断表达式是否为NULLselect ISNULL(null); – 1
NULLIF(expr1, expr2)比较两个字符串,如果字符串expr1与expr2相等 返回NULL,否则返回expr1select nullif(25, 25); – NULL

[2].示例

-- 控制流函数
select if(5 > 3, '大于', '小于'); -- 大于
select *, if(score >= 85, '优秀', '及格') flag from score;

select ifnull(5, 0); -- 5
select ifnull(null, 0); -- 0
select *, ifnull(conn, 0) conn_flag from emp;

select isnull(5); -- 1
select isnull(NULL); -- 0

select nullif(12, 12); -- null
select nullif(12, 13); -- 12

(2).case when语句

[1].分类:

格式解释示例
case expression WHEN condtion1 THEN result1 WHEN condtion2 THEN result2 … WHEN condtionN THEN resultN ELSE resultENDCASE表示函数开始,END表示结束。如果condition1. 则返回result1,如果condition2. 则返回result2,当全部不成立则返回result, 而当有一个成立之后,后面的就不执行了。select case 100 when 50 then ‘tom’ when 100 then ‘mary’ else ‘tin’ end; – maryselect case when 1=2 then ‘tom’ when 2=2 then ‘mary’ else ‘tin’ end; – mary

[2].示例:

select
   case 9
	 when 1 then '1'
	 when 2 then '2'
	 when 3 then '3'
	 when 4 then '4'
	 when 5 then '5'
	 else
	   'aa' 
	 end; -- 3

8.MySQL函数-窗口函数

(1).介绍

[1].MySQL8.0新增窗口函数,窗口函数又称为开窗函数,与Oracle窗口函数类似,属于MySQL的一大特点

[2].非聚合窗口函数是相对于聚函数来说的。聚函数是对一组数据计算后返回单个值(即分组),非聚合函数一次只会处理一行数据。窗口聚合函数在行记录上计算某个字段的结果时,可将窗口范围内的数据输入到聚合函数中,并不改变行数。
在这里插入图片描述

(2).分类

在这里插入图片描述

(3).语法结构

window_function (expr) OVER (
    PARTITION BY ...
    ORDER BY ...
    frame_clause
)

其中,window_function是窗口函数的名称;expr是参数,有些函数不需要参数;OVER子句包含三个选项:

[1].分区(PARTITION BY)

PARTITION BY选项用于将数据拆分成多个分区(组),它的作用类似于GROUP BY分组。如果省略了PARTITION BY,所有的数据作为一个组进行计算

[2].分区(ORDER BY)

OVER子句中的ORDER BY选项用于指定分区内的排序方式,与ORDER BY子句的作用类似

[3].以及窗口大小(frame_clause)

frame_clause选项用于在当前分区内指定一个计算窗口,也就是一个与当前行相关的数据子集。

(4).序号函数

序号函数有三个:ROW_NUMBER(), RANK(), DENSE_RANK()可以用来实现分组排序,并添加序号。

[1].格式

row_number()|rank()|dense_rank() over (
    partition by ...
    order by ...
)

[2].示例

-- 创建employee表
create table employee(
  dname varchar(20), -- 部门名
  eid varchar(20), 
  ename varchar(20),
  hiredate date, -- 入职日期
  salary double -- 薪资  
);
-- 插入数据
insert into employee values('研发部', '1001', '刘备', '2021-11-01', 3000);
insert into employee values('研发部', '1002', '关羽', '2021-11-02', 5000);
insert into employee values('研发部', '1003', '张飞', '2021-11-03', 7000);
insert into employee values('研发部', '1004', '赵云', '2021-11-04', 7000);
insert into employee values('研发部', '1005', '马超', '2021-11-05', 4000);
insert into employee values('研发部', '1006', '黄忠', '2021-11-06', 4000);

insert into employee values('销售部', '1007', '曹操', '2021-11-01', 2000);
insert into employee values('销售部', '1008', '许褚', '2021-11-02', 3000);
insert into employee values('销售部', '1009', '典韦', '2021-11-03', 5000);
insert into employee values('销售部', '1010', '张辽', '2021-11-04', 6000);
insert into employee values('销售部', '1011', '徐晃', '2021-11-05', 9000);
insert into employee values('销售部', '1012', '曹洪', '2021-11-06', 6000);
-- 对每个部门员工按照薪资排序,并给出排名
select 
dname,
ename,
salary,
ROW_NUMBER() over (PARTITION by dname ORDER BY salary desc) as rn 
from employee;
--------------------------------------------------------------------------------
select
dname,
ename,
salary,
rank() over (partition by dname order by salary desc) as rn
from employee;
---------------------------------------------------------------------------------
select
dname,
ename,
salary,
dense_rank() over (partition by dname order by salary desc) as rn
from employee;
-- 求出每个部门薪资排在前三名的员工 - 分组求TOPN
select * from(
    select
    dname,
    ename,
    salary,
    dense_rank() over (partition by dname order by salary desc) as rn
) as t where t.rn <= 3;
-- 对所有员工进行全局排序(不分组)
select
dname,
ename,
salary,
rank() over (order by salary desc) as rn
from employee;

(5).开窗聚合函数 - SUM, AVG, MIN, MAX

[1].概念

在窗口中每条记录动态地应用聚合函数(SUM(), AVG(), MAX(), MIN(), COUNT()), 可动态计算在指定的窗口内的各种聚合函数值

[2].示例

-- 开窗聚合函数
select 
dname,
ename,
salary,
sum(salary) over(PARTITION by dname order by hiredate) as pv1
from employee;

select cookieid, createtime, pv,
sum(pv) over(partition by cookieid) as pv3
from itcast_t1; -- 如果没有order by排序语句 默认把分组内的所有数据进行sum操作

(6).分布函数-CUME_DIST和PERCENT_RANK

[1].介绍-CUME_DIST()

[a].用途

分组内小于,等于当前rank值的行数/分组内总行数

[b].应用场景

查询小于等于当前薪资(salary)的比例

[c].示例
select
dname,
ename,
salary,
cume_dist() over (order by salary) as rn1, -- 没有partition语句 所有的数据位于一组
cume_dist() over (partition by dept ORDER BY salary) as rn2
from employee;

[2].介绍-PERCENT_RANK

[a].用途

每行按照公式(rank - 1)/(row - 1 )进行计算。其中,rank为RANK()函数产生的序号,rows为当前窗口的记录总行数

[b].应用场景

不常用

[c].示例
select 
dname,
ename,
salary,
rank() over(partition by dname order by salary desc) as rn,
PERCENT_RANK() over(partition by dname order by salary desc) as rn2
from employee;

(7).前后函数-LAG和LEAD

[1].介绍:

用途:返回位于当前行的前n行(LAG(expr, n))或后n行(LEAD(expr, n))的expr的值

应用场景:查询前1名同学的成绩和当前同学成绩的差值

[2].示例

-- lag用法
select 
dname,
ename,
hiredate,
salary,
lag(hiredate, 1, '2000-01-01') over(partition by dname order by hiredate) as last_1_time,
lag(hiredate, 2) over(partition by dname order by hiredate) as last_2_time
from employee;
-- lead用法
select 
dname,
ename,
hiredate,
salary,
lead(hiredate, 1, '2000-01-01') over(partition by dname order by hiredate) as last_1_time,
lead(hiredate, 2) over(partition by dname order by hiredate) as last_2_time
from employee;

(8).头尾函数-FIRST_VALUE和LAST_VALUE

[1].介绍

用途:返回第一个(FIRST_VALUE(expr))或最后一个(LAST_VALUE(expr)) expr的值

应用场景:截止到当前,按照日期排序查询第一个入职和最后一个入职员工的薪资

注意:如果不指定order by, 则进行排序混乱,会出现错误

[2].示例

select 
dname,
ename,
hiredate,
salary,
first_value(salary) over(partition by dname order by hiredate) as first,
LAST_VALUE(salary) over(partition by dname order by hiredate) as last
from employee;

(9).其他函数-NTH_VALUE(expr, n), NTILE(n)

[1].NTH_VALUE(expr, n)

[a].介绍

用途:返回窗口中第n个expr的值。expr可以是表达式,也可以是别名
应用场景:截止到当前薪资,显示每个员工的薪资中排序第2或第3薪资

[b].示例
-- 查询每个部门截止目前薪资排在第二和第三的员工信息
select 
dname,
ename,
hiredate,
salary,
nth_value(salary, 2) over(partition by dname order by hiredate) as second_score,
nth_value(salary, 3) over(partition by dname order by hiredate) as third_score,
from employee;

[2].NTILE

[a].介绍

用途:将分区中的有序数据分为n个等级,记录等级数

应用场景:将每个部门员工按照入职日期分成3组

[b].示例
-- 根据入职日期将每个部门的员工分成3组
select 
dname,
ename,
hiredate,
salary,
ntile(3) over(partition by dname order by hiredate) as rn
from employee;

-- 取出每个部门的第一组员工
 select 
 *
 from 
 (
    select 
    dname,
    ename,
    hiredate,
    salary,
    ntile(3) over(partition by dname order by hiredate) as rn
    from employee;    
 ) t
 where t.rn = 1;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值