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