天天看点

数据库SQL实战-异常的邮件概率(mysql)1. 出现三次以上相同积分的情况2. 刷题通过的题目排名3. 找到每个人的任务4. 异常的邮件概率

1. 出现三次以上相同积分的情况

1.1 题目描述

在牛客刷题的小伙伴们都有着牛客积分,积分(grade)表简化可以如下:
数据库SQL实战-异常的邮件概率(mysql)1. 出现三次以上相同积分的情况2. 刷题通过的题目排名3. 找到每个人的任务4. 异常的邮件概率
id为用户主键id,number代表积分情况,让你写一个sql查询,积分表里面出现三次以及三次以上的积分,查询结果如下:
数据库SQL实战-异常的邮件概率(mysql)1. 出现三次以上相同积分的情况2. 刷题通过的题目排名3. 找到每个人的任务4. 异常的邮件概率

1.2 语句实现

select number 
from grade
group by number
having count(id) >= 3;
           

2. 刷题通过的题目排名

2.1 题目描述

在牛客刷题有一个通过题目个数的(passing_number)表,id是主键,简化如下:
数据库SQL实战-异常的邮件概率(mysql)1. 出现三次以上相同积分的情况2. 刷题通过的题目排名3. 找到每个人的任务4. 异常的邮件概率

第1行表示id为1的用户通过了4个题目;

第6行表示id为6的用户通过了4个题目;

请你根据上表,输出通过的题目的排名,通过题目个数相同的,排名相同,此时按照id升序排列,数据如下:

数据库SQL实战-异常的邮件概率(mysql)1. 出现三次以上相同积分的情况2. 刷题通过的题目排名3. 找到每个人的任务4. 异常的邮件概率

id为5的用户通过了5个排名第1,

id为1和id为6的都通过了2个,并列第2

2.2 语句实现

-- rank() over:例1,2,2,4
-- dense_rank() oveer:例1,2,2,3
-- row_number() over:例1,2,3,4连续排名
select id, number, dense_rank() over (order by number desc) as t_rank
from passing_number
order by number desc, id;
           

3. 找到每个人的任务

3.1 题目描述

有一个person表,主键是id,如下:
数据库SQL实战-异常的邮件概率(mysql)1. 出现三次以上相同积分的情况2. 刷题通过的题目排名3. 找到每个人的任务4. 异常的邮件概率
有一个任务(task)表如下,主键也是id,如下:
数据库SQL实战-异常的邮件概率(mysql)1. 出现三次以上相同积分的情况2. 刷题通过的题目排名3. 找到每个人的任务4. 异常的邮件概率
请你找到每个人的任务情况,并且输出出来,没有任务的也要输出,而且输出结果按照person的id升序排序,输出情况如下:
数据库SQL实战-异常的邮件概率(mysql)1. 出现三次以上相同积分的情况2. 刷题通过的题目排名3. 找到每个人的任务4. 异常的邮件概率

3.2 语句实现

select p.id, p.name, t.content 
from person p
left join task t
on p.id = t.person_id
order by p.id;
           

4. 异常的邮件概率

4.1 题目描述

现在有一个需求,让你统计正常用户发送给正常用户邮件失败的概率:

有一个邮件(email)表,id为主键, type是枚举类型,枚举成员为(completed,no_completed),completed代表邮件发送是成功的,no_completed代表邮件是发送失败的。简况如下:

数据库SQL实战-异常的邮件概率(mysql)1. 出现三次以上相同积分的情况2. 刷题通过的题目排名3. 找到每个人的任务4. 异常的邮件概率

第1行表示为id为2的用户在2020-01-11成功发送了一封邮件给了id为3的用户;

第3行表示为id为1的用户在2020-01-11没有成功发送一封邮件给了id为4的用户;

第6行表示为id为4的用户在2020-01-12成功发送了一封邮件给了id为1的用户;

下面是一个用户(user)表,id为主键,is_blacklist为0代表为正常用户,is_blacklist为1代表为黑名单用户,简况如下:

数据库SQL实战-异常的邮件概率(mysql)1. 出现三次以上相同积分的情况2. 刷题通过的题目排名3. 找到每个人的任务4. 异常的邮件概率

第1行表示id为1的是正常用户;

第2行表示id为2的不是正常用户,是黑名单用户,如果发送大量邮件或者出现各种情况就会容易发送邮件失败的用户

……

第4行表示id为4的是正常用户

现在让你写一个sql查询,每一个日期里面,正常用户发送给正常用户邮件失败的概率是多少,结果保留到小数点后面3位(3位之后的四舍五入),并且按照日期升序排序,上面例子查询结果如下:

数据库SQL实战-异常的邮件概率(mysql)1. 出现三次以上相同积分的情况2. 刷题通过的题目排名3. 找到每个人的任务4. 异常的邮件概率

结果表示:

2020-01-11失败的概率为0.500,因为email的第1条数据,发送的用户id为2是黑名单用户,所以不计入统计,正常用户发正常用户总共2次,但是失败了1次,所以概率是0.500;

2020-01-12没有失败的情况,所以概率为0.000.

(注意: sqlite 1/2得到的不是0.5,得到的是0,只有1*1.0/2才会得到0.5,sqlite四舍五入的函数为round)

4.2 语句实现

-- round(x,d):x指要处理的数,d指要保留几位小数,当d为负数时,代表指定小数点左边第d位为0,小数位也为0
-- round(x):即d为0,小数位为0
select e.date, round(sum(case e.type
                            when 'no_completed' then 1 
                            else null end)*1.0/ count(e.type),3) as p
from email e
join user u1 on e.send_id = u1.id
join user u2 on e.receive_id = u2.id
where u1.is_blacklist = 0 
and u2.is_blacklist = 0
group by e.date
order by e.date;