SQL實戰 9.高頻SQL面試題 網站訪客最近登錄日期系列



最近登錄日期(一)

描述

某網站每天有很多人登錄,請你統計一下該網站每個用戶最近登錄是哪一天,用的是什么設備.
有一個登錄(login)記錄表,簡況如下:

第1行表示user_id為2的用戶在2020-10-12使用了客戶端id為1的設備登錄了該網站
。。。
第4行表示user_id為3的用戶在2020-10-13使用了客戶端id為2的設備登錄了該網站

還有一個用戶(user)表,簡況如下:



還有一個客戶端(client)表,簡況如下:


請你寫出一個sql語句查詢每個用戶最近一天登錄的日子,用戶的名字,以及用戶用的設備的名字,並且查詢結果按照user的name升序排序,上面的例子查詢結果如下:
 
查詢結果表明:
fh最近的登錄日期在2020-10-13,而且是使用ios登錄的
wangchao最近的登錄日期也是2020-10-13,而且是使用ios登錄的

SQL如下

select  u_n,c_n ,date from 
(
select a.user_id,a.date,b.name as u_n,c.name as c_n,row_number() over(partition by user_id order by date desc)as rn
    from login a left join user b on a.user_id=b.id left join client c on a.client_id=c.id
)a where rn=1 
order by u_n

 

 

最近登錄日期(二)

描述

某網站每天有很多人登錄,請你統計一下該網站新登錄用戶的次日成功的留存率,
有一個登錄(login)記錄表,簡況如下:

第1行表示user_id為2的用戶在2020-10-12使用了客戶端id為1的設備第一次新登錄了該網站
。。。
第4行表示user_id為3的用戶在2020-10-12使用了客戶端id為2的設備登錄了該網站
。。。
最后1行表示user_id為1的用戶在2020-10-14使用了客戶端id為2的設備登錄了該網站


請你寫出一個sql語句查詢新登錄用戶次日成功的留存率,即第1天登陸之后,第2天再次登陸的概率,保存小數點后面3位(3位之后的四舍五入),上面的例子查詢結果如下:

查詢結果表明:
user_id為1的用戶在2020-10-12第一次新登錄了,在2020-10-13又登錄了,算是成功的留存
user_id為2的用戶在2020-10-12第一次新登錄了,在2020-10-13又登錄了,算是成功的留存
user_id為3的用戶在2020-10-12第一次新登錄了,在2020-10-13沒登錄了,算是失敗的留存
user_id為4的用戶在2020-10-13第一次新登錄了,在2020-10-14沒登錄了,算是失敗的留存
固次日成功的留存率為 2/4=0.5
(sqlite里查找某一天的后一天的用法是:date(yyyy-mm-dd, '+1 day'),四舍五入的函數為round,sqlite 1/2得到的不是0.5,得到的是0,只有1*1.0/2才會得到0.5
mysql里查找某一天的后一天的用法是:DATE_ADD(yyyy-mm-dd,INTERVAL 1 DAY),四舍五入的函數為round)

 SQL如下

select 
round(count(distinct user_id)*1.0/(select count(distinct user_id) from login) ,3)
from login
where (user_id,date)
in (select user_id,DATE_ADD(min(date),INTERVAL 1 DAY) from login group by user_id);

 


最近登錄日期(三)

描述

牛客每天有很多人登錄,請你統計一下牛客每個日期登錄新用戶個數,
有一個登錄(login)記錄表,簡況如下:

第1行表示user_id為2的用戶在2020-10-12使用了客戶端id為1的設備登錄了牛客網,因為是第1次登錄,所以是新用戶
。。。
第4行表示user_id為2的用戶在2020-10-13使用了客戶端id為2的設備登錄了牛客網,因為是第2次登錄,所以是老用戶
。。
最后1行表示user_id為4的用戶在2020-10-15使用了客戶端id為1的設備登錄了牛客網,因為是第2次登錄,所以是老用戶


請你寫出一個sql語句查詢每個日期登錄新用戶個數,並且查詢結果按照日期升序排序,上面的例子查詢結果如下:


查詢結果表明:
2020-10-12,有3個新用戶(user_id為2,3,1)登錄
2020-10-13,沒有新用戶登錄
2020-10-14,有1個新用戶(user_id為4)登錄
2020-10-15,沒有新用戶登錄

 SQL如下

解法一:暴力破解法,求出每個用戶的首次登陸日期,並統計每個日期的人數即可,但題目要求當天沒有人的話要給出0,所以這里需要join一下自己,取沒有用戶登陸的日期;

select a.date,case when b.cnt is null then 0 else b.cnt end as cnt from 
(select distinct date from login )a left join 
(select date,count(1) as cnt from 
(
select id,user_id,client_id,date,
row_number() over(partition by user_id order by date) as rn from login a 
)a 
where rn=1 group by date
) b
on a.date=b.date

 

解法二: 用 (user_id,date) in (user_id,min(date)) 得到每天登陸的新用戶,最后用sum case when來統計

select distinct date,
sum(case when (user_id,date) in 
 (select user_id,min(date) from login group by user_id )
    then 1 else 0 end   
                        )
from login group by date order by date

 


最近登錄日期(四)

 

描述

某網站每天有很多人登錄,請你統計一下每個日期新用戶的次日留存率。
有一個登錄(login)記錄表,簡況如下:

第1行表示user_id為2的用戶在2020-10-12使用了客戶端id為1的設備登錄了該網站,因為是第1次登錄,所以是新用戶
。。。
第4行表示user_id為2的用戶在2020-10-13使用了客戶端id為2的設備登錄了該網站,因為是第2次登錄,所以是老用戶
。。
最后1行表示user_id為4的用戶在2020-10-15使用了客戶端id為1的設備登錄了該網站,因為是第2次登錄,所以是老用戶



請你寫出一個sql語句查詢每個日期新用戶的次日留存率,結果保留小數點后面3位數(3位之后的四舍五入),並且查詢結果按照日期升序排序,上面的例子查詢結果如下:

查詢結果表明:
2020-10-12登錄了3個(user_id為2,3,1)新用戶,2020-10-13,只有2個(id為2,1)登錄,故2020-10-12新用戶次日留存率為2/3=0.667;
2020-10-13沒有新用戶登錄,輸出0.000;
2020-10-14登錄了1個(user_id為4)新用戶,2020-10-15,user_id為4的用戶登錄,故2020-10-14新用戶次日留存率為1/1=1.000;
2020-10-15沒有新用戶登錄,輸出0.000;
(注意:sqlite里查找某一天的后一天的用法是:date(yyyy-mm-dd, '+1 day'),sqlite里1/2得到的不是0.5,得到的是0,只有1*1.0/2才會得到0.5)

SQL如下

select c.date,
round(count(d.user_id)/count(*),3)as p
from
(select a.date,b.user_id from
(select distinct l1.date from login l1)a left join 
(select l2.user_id,min(l2.date) as f_date from login l2 group by l2.user_id)b
on a.date=b.f_date
) as c left join (select distinct l3.user_id
from login l3,login l4
where l3.user_id=l4.user_id
and DATE_ADD(l3.date,INTERVAL 1 DAY)=l4.date) as d on c.user_id = d.user_id
group by c.date

 

最近登錄日期(五)

描述

牛客每天有很多人登錄,請你統計一下牛客每個用戶查詢刷題信息,包括: 用戶的名字,以及截止到某天,累計總共通過了多少題。 不存在沒有登錄卻刷題的情況,但是存在登錄了沒刷題的情況,不會存在刷題表里面,有提交代碼沒有通過的情況,但是會記錄在刷題表里,只不過通過數目是0。
有一個登錄(login)記錄表,簡況如下:

第1行表示user_id為2的用戶在2020-10-12使用了客戶端id為1的設備登錄了牛客網
。。。
第5行表示user_id為3的用戶在2020-10-13使用了客戶端id為2的設備登錄了牛客網


有一個刷題(passing_number)表,簡況如下:

第1行表示user_id為2的用戶在2020-10-12通過了4個題目。
。。。
第3行表示user_id為1的用戶在2020-10-13提交了代碼但是沒有通過任何題目。
第4行表示user_id為4的用戶在2020-10-13通過了2個題目


還有一個用戶(user)表,簡況如下:





請你寫出一個sql語句查詢刷題信息,包括: 用戶的名字,以及截止到某天,累計總共通過了多少題,並且查詢結果先按照日期升序排序,再按照姓名升序排序,有登錄卻沒有刷題的哪一天的數據不需要輸出,上面的例子查詢結果如下:

查詢結果表明:
fh在2020-10-12為止,總共通過了4道題,輸出為4
wangchao在2020-10-12為止,總共通過了1道題,總計為1
tm在2020-10-12為止只登陸了沒有刷題,故沒有顯示出來
tm在2020-10-13為止刷了題,但是卻沒有通過任何題目,總計為0
wangchao在2020-10-13通過2道,但是加上前面2020-10-12通過1道,故在2020-10-13為止總共通過了3道題,總計為3

解題思路 

1.先找出每個用戶都在那一天登陸了:

select distinct user_id,date from login

 

2.然后去與passing_number表關聯小於或等於當前日期的數據,當然也別忘了關聯user表去取一下name:

select c.name,a.user_id ,a.date,b.number from 
(select distinct user_id,date from login) a,
passing_number b ,
 user c    
    where a.user_id=b.user_id and a.user_id =c.id 
and b.date<=a.date

 

3.最后求每個user每天的刷題數量,用sum()+group by 即可:

SQL如下

select name,date,sum(number) from 
(
select c.name,a.user_id ,a.date,b.number from 
(select distinct user_id,date from login) a,
passing_number b ,
 user c    
    where a.user_id=b.user_id and a.user_id =c.id 
and b.date<=a.date
) b group by name ,date order by date, name

 本文SQL題目來源於牛客網

 

 

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM