0
点赞
收藏
分享

微信扫一扫

MYSQL学习笔记(6)

年迈的代码机器 2022-03-25 阅读 86

一些补充知识

replace

replace函数可以将表里面的某个字段值替换成另一个字符,批量操作时直接用sql会比程序来判断执行更快
replace(str,str1,str2);
str:源字符串
str1:待替换字符串
str2:替换后的字符串

例题1.平均播放进度大于60%的视频类别

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

问题分析

(1)播放进度——
播放时长:timestampdiff(second,start_time,end_time) watch_time
视频时长:duration
(timestampdiff(second,start_time,end_time)/duration)*100
(2)如果大于视频时长播放进度记为100%——
if(watch_time>duration,100,(watch_time/duration)*100)
(3)加%拼接:concat((timestampdiff(second,start_time,end_time)/duration)*100,’%’)
(4)保留两位小数:round(,2)
(5)进度大于60%输出——
一开始并不知道replace函数所以在与%拼接前又嵌套了一层筛选,用where筛选了大于60的;
(6)平均——avg();
(7)排序——ORDER BY ;

过程重写

不用replace

SELECT tag,CONCAT(avg_play_progress1,'%') avg_play_progress
FROM
(SELECT tag,round(play_progress,2) avg_play_progress1
FROM
(SELECT t1.tag,
avg(if(watch_time>duration,100,(watch_time/duration)*100)) play_progress
FROM
(SELECT tbu.video_id,tag,
timestampdiff(second,start_time,end_time) watch_time
FROM tb_user_video_log tbu LEFT JOIN tb_video_info tbv
ON tbu.video_id=tbv.video_id) t1 
LEFT JOIN tb_video_info tbv ON t1.video_id=tbv.video_id
GROUP BY tag) t2
WHERE play_progress>60)t3
ORDER BY avg_play_progress1 desc;

用replace

select a.tag, avg_play_progress
from (select tag, 
   concat(round(avg(case when timestampdiff(second, start_time, end_time)>=duration then 1 else 
   timestampdiff(second, start_time, end_time)/duration end)*100,2),'%') avg_play_progress
   from tb_user_video_log t1
   join tb_video_info t2
   on t1.video_id=t2.video_id
   group by tag) a
where replace(avg_play_progress,'%','') > 60
order by avg_play_progress DESC

细节问题

(1)JOIN表之后相同列要加a.字段,不然会模糊不清报错。

rows/range

RANGE表示按照值的范围进行范围的定义,而ROWS表示按照行的范围进行范围的定义;
“RANGE|ROWS BETWEEN 边界规则1 AND 边界规则2”部分用来定位聚合计算范围,这个子句又被称为定位框架。
在这里插入图片描述
使用ROWS选项定义当前行的固定前后记录。这里看到的行取决于窗口的ORDER BY从句,也可以说在物理级别定义的窗口;
RANGE 是逻辑窗口,是指定当前行对应值的范围取值,列数不固定,只要行值在范围内,对应列都包含在内。

例题2.国庆期间每类视频点赞量和转发量

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

问题分析

开窗函数思路:
(1)每天的近一周点赞量——也就是分为三个时间段(9.24-10.1;9.26-10.2;9.27-10.3)
同理一周内最大单天转发量也是三个时间段的,像是一个移动的固定大小的框只需要按顺序移动一行就可以了,用到窗口函数加上前后行数的限制条件
(2)先把每天多行记录合并成group by tag,dt的新表,sum出点赞和转发的数量,然后在这个表的基础上用开窗函数移动计算;
时间差思路:
待更新

过程重写

SELECT
  *
FROM (
  SELECT
    tag,
    dt,
    SUM(like_cnt) OVER (PARTITION BY tag ORDER BY dt DESC ROWS BETWEEN CURRENT ROW AND 6 FOLLOWING)
 sum_like_cnt_7d,
    MAX(retweet_cnt) OVER (PARTITION BY tag ORDER BY dt DESC ROWS BETWEEN CURRENT ROW AND 6 FOLLOWING)
 sum_retweet_cnt_7d
  FROM (
    SELECT
      tag,
      DATE(start_time) dt,
      SUM(if_like) like_cnt,
      SUM(if_retweet) retweet_cnt
    FROM tb_video_info
    LEFT JOIN tb_user_video_log USING(video_id)
    WHERE DATE(start_time) BETWEEN '2021-09-25' AND '2021-10-03'
    group by 1,2) t1
  ) t2
GROUP BY 1, 2
HAVING dt BETWEEN '2021-10-01' AND '2021-10-03'
ORDER BY 1 DESC, 2;

细节问题

(1)注意运算顺序,窗口函数筛选完之后再套一层select再having不然直接having是错误的
(2)窗口desc rows betweem current row and 6 following;如果asc排序则改成between 6 preceding and current row结果相同;

interval

interval函数和interval关键词是两种不同的东西
(1)INTERVAL()函数
INTERVAL()函数可以返回分段后的结果
INTERVAL(N,N1,N2,N3,…)
N1<N2<N3…
如果N<N1,则返回0,
如果N1<=N<N2,则返回1,
如果N2<=N<N3,则返回2。
区间是左闭右开的;

(2)INTERVAL关键字可以用在DATE_SUB(),SUBDATE(),ADDDATE()等函数中。
例1:查询两天前的时间:

SELECT NOW(),SUBDATE(NOW(),INTERVAL 2 DAY);

例题2中有用DATE_SUB()的写法,2021-10-01减去6天,也就是2021-09-25

DATE_SUB("2021-10-01",interval 6 day)
举报

相关推荐

0 条评论