# 多关键字排序

### 学生们参加各科测试的次数

``````SELECT
s.student_id,
s.student_name,
sb.subject_name,
COUNT(e.student_id) AS attended_exams
FROM
Students s
join Subjects sb
LEFT JOIN Examinations e
on e.subject_name = sb.subject_name and e.student_id = s.student_id
GROUP BY
s.student_id,sb.subject_name
ORDER BY
s.student_id,sb.subject_name;
``````

# 在group_concat中使用排序

group_concat是分组后常用的一个函数，他能将一个分组内的内容按照一定格式陈列出来。

### 按日期分组销售产品

``````select
sell_date,
count(distinct product) as num_sold,
group_concat(distinct product order by product) as products
from
activities
group by
sell_date
;
``````

# sum配合case when

case-when-then-else-end这套分支语句是功能非常强大的，更为厉害的是，他可以配合着聚合函数一起使用，对分组中的每一个成员进行条件判断，产生不同的返回。

### 即时食物配送I

``````select
round(sum(case when order_date = customer_pref_delivery_date then 1 else 0 end)/count(delivery_id)*100,2) as immediate_percentage
from
delivery
;
``````

### 广告效果

``````select
ifnull(round(sum(case when action = 'Clicked' then 1 else 0 end) / sum(case when action = 'Clicked' or action = 'viewed' then 1 else 0 end) * 100,2),0) as ctr
from
group by
order by
;
``````

# 使用union

union可以联合两个查询结果，但是需要其字段名称和类型必须相同。

union算是个挺偏的知识点的。在所有的54题中仅出现过一次以其为较优答案的题目，就是下面这个题。

### 制作绘画柱状图

``````select '[0-5>' as bin,count(*) as total
from sessions
where duration / 60 >= 0 and duration / 60 < 5

union

select '[5-10>' as bin, count(*) as total
from sessions
where duration / 60 >= 5 and duration / 60 < 10

union

select '[10-15>' as bin,count(*) as total
from sessions
where duration / 60 >= 10 and duration / 60 < 15

union

select '15 or more' as bin,count(*) as total
from sessions
where duration / 60 >= 15
;
``````

# 善用子查询

## 配合in语句

### 销售分析II

``````select
FROM
Sales
where
in(
SELECT
FROM
Sales s
JOIN Product p
ON p.product_id = s.Product_id
where
product_name = 'S8'
)
and
SELECT
FROM
Sales s
JOIN Product p
ON p.product_id = s.Product_id
where
product_name = 'iphone')
;
``````

### 游戏玩法分析II

``````select
player_id,
device_id
from
activity
where
(player_id,event_date) in(
select
player_id,
min(event_date)
from
activity
group by
player_id
);
``````

## 作为元素进行运算

### 好友申请I：总体通过率

``````select
round(ifnull(
(select count(distinct requester_id,accepter_id) from request_accepted)/
(select count(distinct sender_id,send_to_id) from friend_request)
,0),2) as accept_rate
;
``````

# 使用自联结

### 连续空余座位

``````select
c1.seat_id
from
cinema c1
left join cinema c2 on c1.seat_id = c2.seat_id - 1
left join cinema c3 on c1.seat_id = c3.seat_id + 1
where
c1.free = 1
and
(
c2.free = 1
or
c3.free = 1
)
;
``````