刷完了簡單和中等難度的資料庫題目,對sql中的一些語法特性有了簡單的了解,算是學會了挺多思路,還有很多的小技巧
總之就是感覺使用sql能完成的任務越來越多了,能解決的業務場景也也越來越復雜了,有許多之前不得不拿到程式中才能處理的資料使用簡單的sql就能夠達成,當事人就很有成就感,
所以刷題整理這個程序還會持續下去,從這篇博文開始,就是中等難度的了,由于題目較長或者題解較簡單稍微復雜,所以為了避免每篇博文過于冗長,暫定是5-6道題一篇,會挑選博主覺得比較有意義的題目(根據博主不算高的水平)
往期的題解會放在最后,歡迎閱覽、交流、討論,
報告的記錄 II
題目鏈接



這道題,先去記錄中查詢出所有被舉報的條目,然后讓這些記錄和被移除的表單進行聯結(注意使用內連接,方便統計),
接著按照日期分組,使用聚合函式配合case陳述句計算出每一天的比率,
那么最后再對所有日期的比率計算平均值,轉化成百分數,保留兩位小數輸出即可
# Write your MySQL query statement below
select
round(avg(rate) * 100,2) average_daily_percent
from
(
select
action_date,
sum(case when r.remove_date is null then 0 else 1 end)/count(a.post_id) rate
from
(
select
distinct post_id,
action_date
from
actions
where
action = 'report'
and
extra = 'spam'
) a
left join removals r on r.post_id = a.post_id
group by
action_date
)t
;
指定日期的產品
題目鏈接


這個題,需要我們統計在某日期時所有商品的價格,這道題的難點在于,商品價格取決于最后一次改變定價的價格,其中還存在價格沒有改變過的情況,
解決這個問題的子問題,就是要找出每個商品在該日期前的最新一次的價格修改日期,進而獲得最新價格,
我們可以先使用where子句篩選出所有在該日期前的記錄,并將這些記錄按照商品分組,使用聚合函式來獲得每個商品最后更改的日期,
但是這樣的查詢只能查詢出每個商品對應的最新修改日期,并不能獲得該日期的價格,所以我們還需要在外面再寫一層查詢,查詢出每個商品對應日期的價格(這里可以使用where子句中的in條件的多關鍵字判定)
此時這張表中的每條記錄就是每個商品最新的價格了,
但是!!!!
還有一個關鍵的問題,那就是當前所有查詢出來的商品及其價格都是發生過修改的價格,那些沒有發生過任何修改的商品是不在當前表單中的,為了補上這個缺口,還需要再添加一層查詢,這一層可以是在查詢中篩選,也可以使用聯結,總之就是補上所有沒有修改過價格的商品即可,
# Write your MySQL query statement below
select
ids.product_id,
(case when prices.new_price is null then 10 else prices.new_price end) as price
from
(
select
distinct product_id
from
products
) ids
left join(
select
product_id,
new_price
from
products
where
(product_id,change_date) in (
select
product_id,
max(change_date) as change_date
from
products
where
change_date <= '2019-08-16'
group by
product_id
)
) prices on ids.product_id = prices.product_id
;
市場分析 I
題目鏈接



這道題需要我們查詢出每個用戶的注冊日期和2019年的訂單數量,
簡單分析一下不難發現,這個題的兩個需求沒有必然聯系,
于是我們可以分開查詢最后再聯結到一起,
對于注冊時間,這個資訊已經在用戶表單中存在了,所以任務只剩下了一件,就是查詢出每個用戶在2019年的訂單數并將它們聯結到用戶表上,
統計訂單數量是個簡單的問題,先用where將所有2019年的訂單篩選出來,接著按照用戶進行分組,再分別使用聚合函式統計即可,
最后!!!記得處理沒有訂單的情況,使用ifnull來單獨處理那些null值,將它們變成0輸出
# Write your MySQL query statement below
select
user_id as buyer_id ,
join_date,
ifnull(item_brand,0) as 'orders_in_2019'
from
users
left join(
select
buyer_id,
count(order_id) as item_brand
from
orders
where
year(order_date) = 2019
group by
buyer_id
)o on o.buyer_id = users.user_id
;
即時食物配送 II
題目鏈接


這道題需要我們統計所有用戶的首次訂單中即時訂單的占比,即時訂單的定義就是下單的日期與需求的日期是同一天,
首先可以先查出所有用戶的首訂單,按照用戶分組,取最小的訂單日期即可,
獲得所有用戶的首訂單之后呢,就需要對所有首訂單進行篩選,這個篩選需要再寫一層查詢,因為剛才的查詢只能確定首訂單的訂單日期并不能獲得其接收日期,
在外層查詢中,可以使用where陳述句的in條件篩選出所有的首訂單,接著使用聚合函式和case篩選出所有的即時訂單(具體的就是比較訂單日期和接受日期是否相同),其中的case也可以使用if來完成,
# Write your MySQL query statement below
select
round(sum(case when order_date = customer_pref_delivery_date then 1 else 0 end) / count(customer_id) * 100,2) as immediate_percentage
from
delivery
where
(customer_id,order_date) in (
select
customer_id,
min(order_date) as order_date
from
delivery
group by
customer_id
)
每月交易 I
題目鏈接


這道題需要我們統計每個國家或地區的事務數及其總金額以及批準的事務數及其總金額,
其實這道題在實作上沒什么繞彎的地方,收錄它的原因在于這道題充分發揮聚合函式配合分支陳述句的篩選功能,
# Write your MySQL query statement below
select
left(trans_date,7) as 'month',
country,
count(id) as trans_count,
sum(case when state = 'approved' then 1 else 0 end) as approved_count,
sum(amount) as trans_total_amount,
sum(case when state = 'approved' then amount else 0 end) as approved_total_amount
from
transactions
group by
concat(year(trans_date),month(trans_date)),country
- 題目總結——經典題目題解與分析(一)–簡單
- 題目總結——經典題目題解與分析(二)–簡單
- 題目總結——經典題目題解與分析(三)–簡單
- 題目總結——經典題目題解與分析 (四)–中等
- 題目總結——經典題目題解與分析 (五)–中等
- 題目總結——經典題目題解與分析 (六)–中等
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/21908.html
標籤:其他
