QUESTION ONE
# Write your MySQL query statement below
select unique_id,name
from EmployeeUNI right join Employees
on EmployeeUNI.id = Employees.id
这题很显然有两张表需要进行连接,在我们确定完要取的字段后,就需要连接两张表,看题目要求可知,当EmployeeUNI 中不存在Employees 的数据时,是以Employees 为准,补null,因为我们需要知道Employees 为主表,因此是 副表 right join 主表(主表 left join 副表),最后连接条件通过on实现。
QUESTON TWO
# Write your MySQL query statement below
select product_name,year,price
from Sales left join Product
on Sales.product_id = Product.product_id
这题还是两张表的连接,值得注意的是示例中并没有出现id = 300的product,因此我们知道Sales为主表(否则会出现Samsung null null的数据),因此 主表 left join 副表实现联立条件。
QUESTION THREE
# Write your MySQL query statement below
select customer_id,count(customer_id) as count_no_trans
from Visits v left join Transactions t
on v.visit_id = t.visit_id
where transaction_id is null
group by customer_id
本题逻辑性有所提升,我们要去找Visits 表中出现的customer_id ,但在Transactions 表中没有出现的customer_id ,同时还需要通过visit_id 出现的次数对两张表进行对比,看上去逻辑十分复杂,但我们换个思路来考虑,如果把Visits 表作为主表将两张表进行拼接会怎样?
通过visit_id 进行拼接,transaction_id 如果没有值就会显示null,因为transaction_id 所在的是副表,这时通过customer_id 进行分组,就可以看到哪些customer_id 对应的transaction_id 是为null的了,然后对customer_id出现的次数进行统计,就是题解。
中间构造的过程表如下:
QUESTION FOUR
select w2.Id
from Weather as w1, Weather as w2
where TIMESTAMPDIFF(DAY, w1.RecordDate, w2.RecordDate) = 1
AND w1.Temperature < w2.Temperature
本题有两个考点,一个是一张表需要分为两个表,有经验的同学知道只需要将Weather 分别取两个别名区分即可,还有一个考点在于如何确定两天的关系是相邻的,这里我推荐使用TIMESTAMPDIFF,因为它的第一个参数可以为年、月、日,值得注意的是差值是第三个参数减去第二个参数,最后用使用where 筛选下。
QUESTION FIVE
# Write your MySQL query statement below
select a.machine_id,
round(sum(b.timestamp - a.timestamp) / count(*),3) as processing_time
from Activity a,Activity b
where a.machine_id = b.machine_id and a.process_id = b.process_id and a.activity_type = 'start' and b.activity_type = 'end'
group by a.machine_id
本题仍然只有一张表,因此仍然需要一表分两表,可以由题意得出a、b两表的machine_id 、process_id 是一样的,只不过a表取的是start,b表取的是end。这样就实现了一张含有machine_id 、process_id 、timestamp (start)、timestamp (end)的表,这样直接进行减法后求和即可,round实现小数的保留。
QUESTION SIX
# Write your MySQL query statement below
select name,bonus
from Employee e left join Bonus b
on e.empId = b.empId
where bonus < 1000 or bonus is null
简单的连接,注意点还是bonus可以出现为null的情况,所以Employee 作为主表进行连接,筛选条件bonus除了小于1000的情况,还要判断为null的情况。
QUESTION SEVEN
# Write your MySQL query statement below
select s.student_id,s.student_name,b.subject_name,count(e.subject_name) as attended_exams
from Students s cross join Subjects b
left join Examinations e
on s.student_id = e.student_id and b.subject_name = e.subject_name
group by s.student_id,b.subject_name
order by s.student_id,b.subject_name
本题涉及到多表的连接,主要的难点在于attended_exams 如何得到,首先我们可以观察到result结果表将student_id 和subject_name 进行了一对一的逻辑对应,这就启发我们需要进行笛卡尔积将student_id 和subject_name 进行配对。然后我们注意到result表中,如果student_id 对应的subject_name 是不存在的,是为0的,可以想到使用count函数进行统计,而count不会对null进行统计,因此得出笛卡尔积后的表为主表,主表 left join Examinations 实现所有人员对应课程的配对情况,然后通过student_id 、subject_name 进行三表联立,分组排序得出结果。
QUESTION EIGHT
# Write your MySQL query statement below
select a.name
from Employee a left join Employee b
on a.id = b.managerId
group by a.name
having count(b.managerId) >= 5
本题在前面的练习后变得较为简单,同样是将一表分为两表,连接条件就是上司的id = 下属的managerId ,在连接两表之后,通过name进行分组,值得注意的是分组完毕后只能使用having进行条件筛选,而不是group by。
QUESTION NINE
# Write your MySQL query statement below
select s.user_id,
round(sum(if(action='confirmed',1,0)) / 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
本题除了需要将两表进行连接外,还需要对confirmation_rate 的获取进行设计,confirmation_rate 是通过某个user_id得到它对应的action等于confirmed的数量除以user_id所有的数据量,有了这个方向,我们先考虑连接两表,result表我们看到user_id=6的情况是存在的,因此Signups 为主表,连接条件便是两者的user_id ,接下来需要考虑confirmation_rate ,round实现四舍五入的两位小数结果,sum对action等于confirmed的情况进行累加,if对action进行判断,最后的除数自然是Signups 表中user_id的数量,因为Confirmations 中的user_id是不全的。