diff --git "a/37 \346\217\255\351\230\263\344\270\275/20231017 \347\254\224\350\256\260.md" "b/37 \346\217\255\351\230\263\344\270\275/20231017 \347\254\224\350\256\260.md" new file mode 100644 index 0000000000000000000000000000000000000000..e177a8f6a5d13936f04670ff2abc189932a5c0ab --- /dev/null +++ "b/37 \346\217\255\351\230\263\344\270\275/20231017 \347\254\224\350\256\260.md" @@ -0,0 +1,313 @@ +# 函数复习 + +### 数学函数 + +```sql +-- 绝对值abs() +select abs(-4) -- 4 + +-- 向上取整 ceil(值) +select ceil(1.5) -- 2 + +-- 向下取整 floor(值) +select floor(1.5) -- 1 + +-- 随机数 rand() +select floor(rand()*100) + +-- 四舍五入,截取 round(值,保留点后n位) +select round(1.6666); +select round(1.6666,2); + +-- 截取 truncate(值,保留点后n位) + +``` + + + +### 字符串函数 + +```sql +-- 字符个数 +select char_length('abc') -- 3 +select char_length('软件工程') -- 4 + +-- 拼接字符串 +select concat('你','好','帅哥') +select concat_ws(',','你','好','帅哥') -- 第一个字符为分隔符 + +-- 去空 +select ltrim(' aaa'); +select rtrim('aaa '); +select trim(' aaa ') + +-- 截取 +select substr('hello',2,3); + +-- 获取子串在字符串的位置 +select position('a' in 'abc'); + +-- 替换 +select replace('aaabbbccc','a','1'); + +``` + + + +### 日期函数 + +```sql +-- 获取当前日期 +select curdate(); + +-- 获取当前时间 +select curtime(); + +-- 获取当前日期时间 +select now(); + +-- 从日期字符串获取日期 +select date('2000-02-02'); +select date('2000-02-02 12:12:12'); -- 只获取日期 + +-- 天数差 +select datediff('2001-02-02','2000-02-02'); -- 前减后 + +-- 指定差 +select timestampdiff(day,'2001-02-02','2000-02-02'); -- 后减前 + +-- 日期减法 +select subdate('2001-02-02',interval 2 day); + +-- 日期加法 +select adddate('2001-02-02',interval 2 day); + +-- 获取某日期中的值 +select year('2001-02-02'); +select day('2001-02-02'); +select dayofyear('2001-02-02'); +select dayofweek('2001-02-02'); + +-- 获取该月最后一天 +select last_day('2001-02-02'); + +-- 日期格式 +select date_format('2001-02-02','%Y') + +``` + +http://www.manongjc.com/detail/29-ensoneygersabbx.html + + + +# 控制流函数 + +```sql +-- if(表达式,值1,值2) true返回值1,false返回值2 +select if(1<2,1,2); + +-- ifnull(值1,值2) 如果值1不为null,返回值1,否则返回值2 +select ifnull(null,2); +select ifnull(1,2); + +-- isnull(表达式) 返回1或0 +select isnull(null); +select isnull(''); + +-- nullif(值1,值2) 比较两个值(字符串),如果当等返回null,否则返回值1 +select nullif(25,25); +``` + +```sql +-- case when +/* +语法1: +case + when 条件表达式1 then 值1 + when 条件表达式2 then 值2 + ... + else 值n +end + +语法2: +case 表达式 + when 条件值1 then 返回值1 + when 条件值2 then 返回值2 + ... + else 返回值n +end + +*/ +``` + + + +# 窗口函数 + +mysql 8.0新增窗口函数(开窗函数)。 + +非聚合窗口函数:是相对于聚合函数来说的,特性为非聚合。一次只处理一行数据。 + +窗口聚合函数:窗口聚合函数在单元行上计算某个字段的结果时,可将窗口范围内的数据输入到聚合函数中,并且不会改变行数。 + + + +### 语法 + +```sql +窗口函数名称(参数) over(partition by ... order by... 窗口大小) +``` + +partition by 分组,等价于group by + +order by 排序 + + + +### 序号函数 + +row_number()、rank()、dense_rank() + + + +### 开窗聚合函数 + +```sql +sum()|avg()|min()|max()|count()| over (partition by ... order by...) +``` + +案例: + +```sql +# 获取各部门薪金总和(合计) +select ename,hiredate,deptno,sal, +sum(sal) over(partition by deptno) 'sum' +from emp; + +# 获取各部门薪金总和(累加) +select ename,hiredate,deptno,sal, +sum(sal) over(partition by deptno order by sal) 'sum' +from emp; +``` + + + +#### 窗口大小 + +```sql +# 开窗范围 +# 获取各部门薪金总和(范围:初始行至当前行) +select ename,hiredate,deptno,sal, +sum(sal) over(partition by deptno rows between unbounded preceding and current row) 'sum' +from emp; + +-- rows 启用窗口大小 +-- between ... and ... 范围区间 +-- unbounded preceding 起始行 +-- current row 当前行 +``` + +不同案例: + +```sql +# 范围:前3行 + 当前行 +sum(sal) over(partition by deptno rows between 3 preceding and current row) + +# 范围:前3行 + 当前行 + 后1行 +sum(sal) over(partition by deptno rows between 3 preceding and 1 following) +-- following指当前行之后的行 + +# 范围:当前行至最后一行 +sum(sal) over(partition by deptno rows between current row and unbounded following) +-- unbounded following 最终行 +``` + + + +### 分布函数 + +##### cume_dist() + +分组内 <= 或 >= 当前值的行数占比(包含当前值本身) + +```sql +# 查询各部门员工小于等于当前薪资的比例 + +select ename,deptno,sal, +cume_dist() over(partition by deptno order by sal) '占比' +from emp; + +-- order by 控制计算的列 +-- asc 小于等于 +-- desc 大于等于 +``` + + + +### 前后函数 + +返回当前行的前某一行的值,或者后某一行的值 + +lag(列名,前第n行) + +lead(列名,后第n行) + +```sql +select ename,deptno,sal, +lag(sal,1) over(partition by deptno order by sal) '前1', +lag(sal,2) over(partition by deptno order by sal) '前2' +from emp; +``` + + + +### 头尾函数 + +返回第一个或最后一个列的值 + +first_value(列名) + +last_value(列名) + +```sql +-- 查询各个部门中,第一个和最后一个入职的员工姓名 +select ename,deptno,sal,hiredate, +first_value(ename) over(partition by deptno order by hiredate) 'first', +last_value(ename) over(partition by deptno order by hiredate) 'last' +from emp; +``` + + + +### 其他函数 + +nth_value(列名,n) —— 返回截止到当前行,该列的第n个值 + +```sql +-- 查找出各个部门,薪资排名第2的员工姓名 +select ename,deptno,sal, +nth_value(ename) over(partition by deptno order by sal) '第二名' +from emp; + +-- 查询全公司,薪资排名第2的员工姓名 +-- 1 +select ename,deptno,sal, +nth_value(ename,2) over(order by sal) '第二名' +from emp; +-- 2 +select ename,deptno,sal, +nth_value(ename,2) over() '第二名' +from emp order by sal; +``` + +ntile(n) —— 将分区中的有序数据分为n个等级,记录等级数 + +```sql +-- 将每个部门员工按照入职日期分成3组 +select ename,deptno,sal, +ntile(3) over(partition by deptno order by hiredate) '组别' +from emp; + +-- 找出每个部门中的老员工?? +``` +