知识点 | 描述 | 题号 |
---|---|---|
datediff | 对日期类型做比较 | 1 |
3+表联表查询 | 层级递进慢慢写 | 2 |
replace函数 | replace(字段名,value1,value2) | 3 |
rank() over (order by xxx desc) | rank并列并舍弃 | 4 |
row_number() | 继续排序 | 4 |
dense_rank() | 并列不舍弃 | 4 |
partition by xxx | 多次重新排序 | 5 |
limit m,n | 其中m是指记录开始的index,从0开始,表示第一条记录;n是指从m+1条开始,取n条。 | 6 |
牛客每天有很多人登录,请你统计一下牛客每个日期新用户的次日留存率。
有一个登录(login)记录表,简况如下:
id | user_id | client_id | date |
---|---|---|---|
1 | 2 | 1 | 2020-10-12 |
2 | 3 | 2 | 2020-10-12 |
3 | 1 | 2 | 2020-10-12 |
4 | 2 | 2 | 2020-10-13 |
5 | 1 | 2 | 2020-10-13 |
6 | 3 | 1 | 2020-10-14 |
7 | 4 | 1 | 2020-10-14 |
8 | 4 | 1 | 2020-10-15 |
请你写出一个sql语句查询每个日期新用户的次日留存率,结果保留小数点后面3位数(3位之后的四舍五入),并且查询结果按照日期升序排序,上面的例子查询结果如下:
date | p |
---|---|
2020-10-12 | 0.667 |
2020-10-13 | 0.000 |
2020-10-14 | 1.000 |
2020-10-15 | 0.000 |
查询结果表明:
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)
SELECT date,IFNULL(ROUND(SUM(CASE WHEN (user_id,date) IN
(SELECT user_id,DATE_ADD(date,INTERVAL -1 DAY) FROM login)
AND (user_id,date) IN (SELECT user_id,MIN(date) FROM login GROUP BY user_id)
THEN 1 ELSE 0 END)/
SUM(CASE WHEN (user_id,date) IN (SELECT user_id,MIN(date) FROM login GROUP BY user_id)
THEN 1 ELSE 0 END),3),0) AS p
FROM login
GROUP BY date
ORDER BY date;
有一个,部门关系表dept_emp简况如下:
emp_no | dept_no | from_date | to_date |
---|---|---|---|
10001 | d001 | 1986-06-26 | 9999-01-01 |
10002 | d001 | 1996-08-03 | 9999-01-01 |
有一个部门经理表dept_manager简况如下:
dept_no | emp_no | from_date | to_date |
---|---|---|---|
d001 | 10002 | 1996-08-03 | 9999-01-01 |
有一个薪水表salaries简况如下:
emp_no | salary | from_date | to_date |
---|---|---|---|
10001 | 88958 | 2002-06-22 | 9999-01-01 |
10002 | 72527 | 1996-08-03 | 9999-01-01 |
获取员工其当前的薪水比其manager当前薪水还高的相关信息,
第一列给出员工的emp_no,
第二列给出其manager的manager_no,
第三列给出该员工当前的薪水emp_salary,
第四列给该员工对应的manager当前的薪水manager_salary
以上例子输出如下:
emp_no | manager_no | emp_salary | manager_salary |
---|---|---|---|
10001 | 10002 | 88958 | 72527 |
select
a.emp_no,
b.emp_no as manager_no,
c.salary as emp_salary,
d.salary as manager_dalary
from
dept_emp a
left join dept_manager b on a.dept_no = b.dept_no
left join salaries c on a.emp_no = c.emp_no
left join salaries d on b.emp_no = d.emp_no
having
c.salary > d.salary
UPDATE
titles_test
set
emp_no = REPLACE (emp_no, "10001", "10005");
链接:https://www.nowcoder.com/questionTerminal/8d2c290cc4e24403b98ca82ce45d04db
来源:牛客网
有一个薪水表salaries简况如下:
emp_no | salary | from_date | to_date |
---|---|---|---|
10001 | 88958 | 2002-06-22 | 9999-01-01 |
10002 | 72527 | 2001-08-02 | 9999-01-01 |
10003 | 43311 | 2001-12-01 | 9999-01-01 |
请你获取薪水第二多的员工的emp_no以及其对应的薪水salary,
若有多个员工的薪水为第二多的薪水,则将对应的员工的emp_no和salary全部输出,并按emp_no升序排序。
emp_no | salary |
---|---|
10002 | 72527 |
select
emp_no,
salary
from
(
select
emp_no,
salary,
rank() over (
order by
salary desc
) as t_rank
from
salaries
) as T
where
T.t_rank = 2
有一个员工表dept_emp简况如下:
emp_no | dept_no | from_date | to_date |
---|---|---|---|
10001 | d001 | 1986-06-26 | 9999-01-01 |
10002 | d001 | 1996-08-03 | 9999-01-01 |
10003 | d002 | 1996-08-03 | 9999-01-01 |
有一个薪水表salaries简况如下:
emp_no | salary | from_date | to_date |
---|---|---|---|
10001 | 88958 | 2002-06-22 | 9999-01-01 |
10002 | 72527 | 2001-08-02 | 9999-01-01 |
10003 | 92527 | 2001-08-02 | 9999-01-01 |
获取每个部门中当前员工薪水最高的相关信息,给出dept_no, emp_no以及其对应的salary,按照部门编号dept_no升序排列,以上例子输出如下:
dept_no | emp_no | maxSalary |
---|---|---|
d001 | 10001 | 88958 |
d002 | 10003 | 92527 |
select
dept_no,
emp_no,
salary as maxSalary
from
(
select
a.dept_no,
a.emp_no,
b.salary,
row_number() over (
partition by
a.dept_no
order by
salary desc
) as tmp_no
from
dept_emp a
left join salaries b on a.emp_no = b.emp_no
) as T
where
T.tmp_no = 1
要求可能有并列的存在
select
*
from
employees
where
hire_date = (
select
hire_date
from
employees
group by
hire_date
order by
hire_date desc
limit
2, 1
)