高频sql 50 题(基础2)

二、连接

1.使用唯一标识码的员工

题目描述

代码编写

select unique_id,name 
from Employees ee left join EmployeeUNI en 
on ee.id=en.id

LEFT JOIN 来确保将所有 Employees 表中的行都包含在结果中,如果 EmployeeUNI 表中没有匹配的行,则默认用 null 填充。

2.产品销售分析

题目描述

代码编写

select product_name,year,price
from Sales s left join Product p 
on s.product_id=p.product_id

3.进店却从未进行过交易的顾客

题目描述

代码编写

select v.customer_id, count(v.customer_id) as count_no_trans 
from Visits v left join Transactions t
on v.visit_id=t.visit_id
where v.visit_id not in (select visit_id from Transactions)
group by v.customer_id

题目的意思理解起来有点绕,简而言之是筛选出那些进店却没有任何交易的顾客(之前进行过交易的顾客在再次进店无任何交易也包括在内),利用左连接列出所有进店的顾客信息,并筛掉有交易的信息,剩下的信息进行分组统计。

4.上升的温度

题目描述

代码编写

select w.id from Weather w  join Weather wh 
on datediff(w.recordDate,wh.recordDate)=1
where w.Temperature>wh.Temperature

通过自连接的方式,我们可以把表格当成两个不同的表格去看,通过DATEDIFF函数将每一天和前一天的温度进行比较,从而找出温度比前一天的温度高的那天。

Tip:

DATEDIFF函数是一个日期函数,用于计算两个日期之间的差距,并以指定的时间单位返回结果,函数形式为DATEDIFF(end_date,start_date)。

5.机器进程平均运行时间

题目描述

代码编写

做法一(比较繁琐的思路):

select a.machine_id,round(avg(a.timestamp-b.timestamp),3) as processing_time 
from Activity a join Activity b 
on a.machine_id=b.machine_id
where a.machine_id=b.machine_id and a.process_id=b.process_id and a.activity_type="end" and b.activity_type="start"
group by a.machine_id

通过自连接的方式把表格看成两个不同的表格a,b,当a表格和b表格的机器编码、进程相同,且a状态为开始,b状态为结束,两者时间相减,得到结果相加之后取平均。

做法二(比较取巧且简便的做法,参考网友做法)

SELECT machine_id, round(avg(if(activity_type = 'start', -timestamp, timestamp))*2, 3)as processing_time 
from Activity 
group by machine_id

利用if判断,当状态为开始,将时间取反(不用自己做差,直接取反),得到所有结果相加之后取平均,实际得到的结果由四位数字相加取平均得到,即sum()/4,而根据题意,机器有两个进程,每个进程的时间差相加再取平均,总的运行时间再除于2得到平均运行时间,即sum()/2,因此结果要再乘上2。

6.员工奖金

题目描述

代码编写

select e.name, b.bonus 
from Employee e left join Bonus b 
on e.empId=b.empId
where  b.bonus<1000 or b.bonus is null

7.学生参加各科测试的次数

题目描述

代码编写

select s.student_id , s.student_name , sub.subject_name , count(e.subject_name) as attended_exams 
from Students s cross join Subjects sub left join Examinations e 
on s.student_id = e.student_id and sub.subject_name = e.subject_name 
group by s.student_id, sub.subject_name 
order by s.student_id ,sub.subject_name

通过交叉联接将表 Student 中的每一行与表 Subject 中的每一行组合在一起,得到两个表中的 student_id 和 subject_name 的所有可能组合(Examinations表格只记录了参加了考试的学生,无缺考学生信息,无法统计出全部结果,因此要先补全考试信息),再通过左连接将应考学生的信息组合一起,并统计每个学生参加每科考试的次数。

8.有直属下属的经理

题目描述

代码编写

select e1.name from Employee e1 join Employee e2 on e1.id=e2.managerId
group by e1.id
having count(e1.id)>=5

通过自连接将经理id和对应的员工id组合一起,对经理id进行分类,并统计经理id次数(对应直属员工个数)。

9.确认率

题目描述

代码编写

做法一:

select s.user_id,round(count(case when action='confirmed' then s.user_id end)/count(s.user_id),2) as confirmation_rate 
from Signups s left join Confirmations c 
on s.user_id=c.user_id
group by s.user_id

Tip:

count(case when then else end)是可以写逻辑,在上述代码可以省略else,此时默认为null,信息也不计入统计范围。

做法二:(参考网友做法)

select s.user_id as 'user_id', round((sum(if (c.action = 'confirmed', 1, 0))) / count(*), 2) as 'confirmation_rate'
from Signups s left join Confirmations c 
on s.user_id = c.user_id
group by s.user_id

sum和if组合使用

  • 16
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值