【数据分析面试】大厂高频SQL笔试题(二)
更多數據分析思維、工具、實際項目和面試面經文章請移步共粽號:【數據分析星球】。
01 寫在前面
無論你是剛畢業的職場小鮮肉、還是想轉行數據分析的小白玩家,只要想進入數據分析的行業,都逃不過數據分析面試的考驗,這里最重要也是最關鍵的一關就是SQL筆試了,不過不用擔心,結合作者6年+的工作和面試經驗,系統全面地整理了數據分析面試中那些高頻出現的以及各大廠的SQL筆試題,學習了這些筆試題的常見套路和解法,把這些題目都刷一遍,在接下來的筆試中應該可以一往無前,收割offer啦!
數據分析筆試中最常見也是最有難度的就是SQL窗口函數了,SQL窗口函數作為SQL的高階語法,也是數分工作中最常用的分析函數,也是面試中最常考查的知識點,本文就講解了各大廠考查的窗口函數題目,通過這些題目就能熟練掌握這個知識點了。
02 計算連續活躍
連續活躍或者登錄的計算是數據分析業務場景中非常經典和常見的問題,而且涉及到的解題思路比較巧妙,所以也是面試筆試中非常喜歡考查的知識點,通過下面的筆試題的詳細講解,希望小伙伴們可以舉一反三,把計算連續這類問題吃透。
記錄用戶活躍時間信息的表user_active如下:
需求:計算連續活躍2天及以上的用戶。
第1步:用戶活躍日期去重
因為一個用戶同一天可能活躍多次,我們只需要知道用戶在某天是否活躍即可,所以需要對用戶id+活躍日期去重。
select DISTINCT
cast(active_time as date) active_day,
userid
from user_active;
查詢結果:
第2步:窗口函數按日期排序
有了第1步去重后的結果,我們可以用row_number() 函數對其進行開窗,以userid分組,日期升序排序,得到每個用戶按照日期升序的排名。
select *,
row_number() over(PARTITION by userid
order by active_day) as rn
from
(
select DISTINCT
cast(active_time as date) active_day,
userid
from user_active;
)a;
查詢結果:
看到這里,有些小伙伴可能就比較疑惑了,為什么要在這一步對日期進行排序呢?這也是計算連續活躍、達標邏輯比較tricky的地方,因為我們用row_number排序之后的名次是連續的,那么如果恰巧日期也是連續的,日期和排序差值不就是一個固定的值了嗎?所有連續的日期是不是都被這個固定的值圈定了?
第3步:確定連續日期的分組
按照上面所說的邏輯,我們使用date_sub函數將當前日期active_day和當前的排序值rn相減,得到一個新的列,命名為"day_group"
select *,
date_sub(active_day,rn) as day_group
from
(
select *,
row_number()over(PARTITION by userid
order by active_day) as rn
from
(
select DISTINCT
cast(active_time as date)active_day,
userid
from user_active;
)a
)b;
查詢結果:
第4步:根據分組列計算連續天數
最后一步,我們直接根據第3步中獲取到的分組列,根據userid和分組列進行分組求count即可。如果是要求連續活躍2天以上,我們直接對聚合后的count 用having進行過濾即可。
select userid,day_group,
count(*) as continous_days
from
(
select *,
date_sub(active_day,rn) day_group
from
(
select ,
row_number()over(PARTITION by
userid order by active_day) as rn
from
(
select DISTINCT
cast(active_time as date)active_day,
userid
from user_active
)a
)b
)c
GROUP BY userid,day_group
having count()>=2;
查詢結果:
到這里結果就出來了,userid為10001和10002的用戶都連續活躍了3天,也就是符合我們條件的用戶。
03 計算累計指標
求累計也是數據分析實際業務中非常常見的場景,截止到每天的累計銷售額、截止到每天的注冊用戶數,可以通過這些指標來看KPI完成情況。所以累計的計算也是筆試中經常出現的題目,下面通過一個案例講解如何計算累計,拋磚引玉,希望大家能舉一反三。
記錄每個商品每天銷售量的表sale_info如下圖:
需求:使用SQL統計出每個商品截至每個月的累積銷量。
第1步:計算每個商品每個月的銷量
為了方便后面的講解,我們把這一步操作的結果存在臨時表tmp中,第1步我們先計算每個商品每個月的銷量。
create table tmp as
select
product_id,
substring(sale_date,1,7) sale_month,
sum(quantity) month_quantity
from sale_info
group by
product_id,
substring(sale_date,1,7);
查詢結果:
第2步:按月累計計算銷量
到這一步,我們用sum開窗函數,對userid進行分組、按照月份進行排序即可完成累計銷量的計算。
select
product_id,
sale_month,
month_quantity,
sum(month_quantity) over(
partition by product_id
order by sale_month) month_all
from tmp;
查詢結果:
完整的SQL代碼如下:
select
product_id,
sale_month,
month_quantity,
sum(month_quantity) over(
partition by product_id
order by sale_month) month_all
from
(
select
product_id,
substring(sale_date,1,7)sale_month,
sum(quantity) month_quantity
from sale_info
group by product_id,
substring(sale_date,1,7)
)t;
04 去除最高最低的平均
salary_info表記錄了每個員工的月工資以及所屬的部門,包含EmpId(員工ID)、Department(部門名稱)、Salary(月工資)。
需求:計算除去部門最高工資,和最低工資的平均工資(字節跳動面試)。
因為要在每個部門內計算平均工資,但是要去除該部門的最高工資和最低工資,所以我們可以考慮使用窗口函數,按照部門進行分組,但是如何將部門的最高工資和最低工資去除呢?我們可以對分組后的數據按照工資分別順序和逆序進行排序,排名第一的就分別是該部門最低和最高工資,將這2個排名第一的記錄去除就是我們要計算的平均工資。
核心是使用窗口函數RANK分別對工資salary進行升序和降序排列,就獲得了該分組內最低和最高的工資,過濾掉這2條記錄再對工資salary進行平均avg即可。
完整SQL代碼如下:
select a.department,avg(a.salary)
from
(
select *,
rank() over( partition by department
order by salary ) rank_asc,
rank() over( partition by department
order by salary desc) rank_desc
from emp
) a
group by a.department
where a.rank_asc >1
and a.rank_desc >1
面試或者筆試的過程中會設定各種各樣的場景,在這些場景下考查我們SQL的查詢能力,但是萬變不離其宗,業務場景只是一個表現形式,抽象為SQL問題后其實基本上就是我們這篇文章介紹的幾類問題:計算累計、連續,分類TopN等。只要掌握這些問題的解法,并且可以舉一反三,并不需要盲目的花費大量的時間精力去刷題,多總結多思考,你就很容易在面試筆試環節脫穎而出了。
以上就是數據分析面試—SQL高頻筆試題系列第2篇的內容,部分數據分析面試筆試請移步共粽號:【數據分析星球】,更多數據分析干貨文章持續更新中,敬請期待,如果覺得不錯,也歡迎分享、點贊和收藏哈~
總結
以上是生活随笔為你收集整理的【数据分析面试】大厂高频SQL笔试题(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python之模块与包(下)
- 下一篇: linux cmake编译源码,linu