文章目录
- 1. 常用函数
- 1. 日期函数
- 2. 行转列(转置)
- 1. 行转列
- 连续N天登录
- 1. 查询出连续三天登录的人员姓名
- N日留存率
- 1. 求用户当天,次日,七日留存率
- 分组内topN
- 1. 求出每个部门工资最高的前三名员工,并计算这些员工的工资占所属部门总工资的百分比
- 注意事项
1. 常用函数
1. 日期函数
常用日期函数:
-- 返回当前日期
select curdate(); # 2024-05-06
-- 返回当前时间
select curtime(); # 21:41:58
-- 返回当前日期加时间
select now(); # 2024-05-06 21:40:53
-- 获取指定date的年份
select year('2024-05-06 21:40:53'); # 2024
-- 获取指定date的月份
select month('2024-05-06 21:40:53'); # 5
-- 获取指定date的年份
select day('2024-05-06 21:40:53'); # 6
-- 返回一个日期/时间值加上一个时间间隔expr后的时间值
select date_add('2024-05-06',interval 1 year ); # 2025-05-06
select date_add('2024-05-06',interval 1 month ); # 2024-06-06
select date_add('2024-05-06',interval 1 day ); # 2024-05-07
-- timestampdiff(单位 ,date1,date2) 返回俩个日期之间的差值
# 单位有:
# 1、YEAR 年
# 2、QUARTER 季度
# 3、MONTH 月
# 4、WEEk 星期
# 5、DAY 天
# 6、HOUR 小时
# 7、MINUTE 分钟
# 8、SECOND 秒
# 9、FRAC_SECOND 毫秒
select timestampdiff(day ,'2024-05-06','2024-06-06'); # 31
-- DATE_FORMAT() 函数用于以不同的格式显示日期/时间数据。
select DATE_FORMAT(NOW(),'%Y-%m-%d'); # 2024-05-06
select DATE_FORMAT(NOW(),'%d %b %Y %T'); # 06 May 2024 22:02:33
-- 返回一个日期/时间值加上一个时间间隔expr后的时间值
select date_sub('2024-05-06',interval 1 day ); # 2024-05-05
2. 行转列(转置)
行转列的常规做法是,group by+sum(if())【或count(if())】
1. 行转列
问题描述:
代码实现:
-- 行转列
-- 建表
create table table2(year int,month int ,amount double) CHARACTER SET utf8 COLLATE utf8_bin;
insert into table2 values
(1991,1,1.1),
(1991,2,1.2),
(1991,3,1.3),
(1991,4,1.4),
(1992,1,2.1),
(1992,2,2.2),
(1992,3,2.3),
(1992,4,2.4);
-- 实现
select year,
sum(if(month = 1,amount,0)) as m1,
sum(if(month = 2,amount,0)) as m2,
sum(if(month = 3,amount,0)) as m3,
sum(if(month = 4,amount,0)) as m4
from table2
group by year;
连续N天登录
1. 查询出连续三天登录的人员姓名
sql实现:
# 建表:
CREATE TABLE game (
name VARCHAR(10) ,
login_date date
) CHARACTER SET utf8 COLLATE utf8_bin;
insert into game values
('张三','2021-01-01'),
('张三','2021-01-02'),
('张三','2021-01-03'),
('张三','2021-01-02'),
('李四','2021-01-01'),
('李四','2021-01-02'),
('王五','2021-01-03'),
('王五','2021-01-02'),
('王五','2021-01-02');
-- sql计算
with t1 as (
select
distinct *
from game
),# 先对数据进行去重
t2 as (
select *,
row_number() over (partition by name order by login_date) as tmp
from t1
),# 采用窗口函数增加一列,对name组内,按日期由大到小进行顺序标号
t3 as (select
*,
date_sub(login_date,interval tmp day ) as tmp_date
from t2)
select
distinct name
from t3
group by name,tmp_date
having count(1) >= 3;
N日留存率
分析:
1. 求用户当天,次日,七日留存率
sql实现:
# 建表
create table if not exists tb_cuid_1d
(
cuid int comment '用户的唯一标识',
os varchar(10) comment '平台',
soft_version int comment '版本',
event_day date comment '日期'
) CHARACTER SET utf8 COLLATE utf8_bin;
insert into tb_cuid_1d values
(1,'android',1,'2020-04-01'),
(1,'android',1,'2020-04-02'),
(1,'android',1,'2020-04-08'),
(2,'android',1,'2020-04-01'),
(3,'android',1,'2020-04-02');
-- sql计算
with t1 as (
select
*
from tb_cuid_1d
where event_day in ('2020-04-01','2020-04-02','2020-04-08')
),
t2 as ( # 计算用户的留存情况,非零表示用户当日的访问次数,null表示用户当日没有访问
select
cuid,
count(if(event_day='2020-04-01',1,null)) as cnt1,
count(if(event_day='2020-04-02',1,null)) as cnt2,
count(if(event_day='2020-04-08',1,null)) as cnt8
from t1
group by cuid
having cnt1 > 0
),
t3 as ( # 计算留存用户数
select
count(cuid) as uv1,
count(if(cnt2 > 0,1,null)) as uv2,
count(if(cnt8 > 0,1,null)) as uv7
from t2
)
select
uv2 / uv1, # 留存率计算
uv7 / uv1
from t3;
分组内topN
需求常见词:【每组xxx的第一个yyy的zzz】【每组xxx的最后一个】
【每组xxx的前n个】【每组最xx的前n个】
公式:row_number() over(partition by 组名) as rn,再筛选rn<=N名
1. 求出每个部门工资最高的前三名员工,并计算这些员工的工资占所属部门总工资的百分比
sql代码:
with t1 as (
select
*,
row_number() over (partition by deptno order by sal desc ) as '部门薪资排名',
sum(sal) over(partition by deptno) as '部门总工资'
from emp
)
select
empno as '员工工号',
sal as '员工工资',
deptno as '部门编号',
部门薪资排名,
部门总工资,
round(sal/部门总工资,2)
from t1
where 部门薪资排名 <= 3;
注意事项
1、group by 语句的使用
在使用group by的语句中,select 后面只能跟group by字段和聚合函数。