【SQL】 牛客网SQL训练Part3 较难难度
获取当前薪水第二多的员工的emp_no以及其对应的薪水salary
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | drop table if exists `employees` ; drop table if exists `salaries` ; CREATE TABLE `employees` ( `emp_no` int (11) NOT NULL , `birth_date` date NOT NULL , `first_name` varchar (14) NOT NULL , `last_name` varchar (16) NOT NULL , `gender` char (1) NOT NULL , `hire_date` date NOT NULL , PRIMARY KEY (`emp_no`)); CREATE TABLE `salaries` ( `emp_no` int (11) NOT NULL , `salary` int (11) NOT NULL , `from_date` date NOT NULL , `to_date` date NOT NULL , PRIMARY KEY (`emp_no`,`from_date`)); INSERT INTO employees VALUES (10001, '1953-09-02' , 'Georgi' , 'Facello' , 'M' , '1986-06-26' ); INSERT INTO employees VALUES (10002, '1964-06-02' , 'Bezalel' , 'Simmel' , 'F' , '1985-11-21' ); INSERT INTO employees VALUES (10003, '1959-12-03' , 'Parto' , 'Bamford' , 'M' , '1986-08-28' ); INSERT INTO employees VALUES (10004, '1954-05-01' , 'Chirstian' , 'Koblick' , 'M' , '1986-12-01' ); INSERT INTO salaries VALUES (10001,88958, '2002-06-22' , '9999-01-01' ); INSERT INTO salaries VALUES (10002,72527, '2001-08-02' , '9999-01-01' ); INSERT INTO salaries VALUES (10003,43311, '2001-12-01' , '9999-01-01' ); INSERT INTO salaries VALUES (10004,74057, '2001-11-27' , '9999-01-01' ); 请你查找薪水排名第二多的员工编号emp_no、薪水salary、last_name以及first_name,不能使用 order by 完成, 以上例子输出为: (温馨提示: sqlite通过的代码不一定能通过mysql,因为SQL语法规定,使用聚合函数时, select 子句中一般只能存在以下三种元素: 常数、聚合函数, group by 指定的列名。 如果使用非 group by 的列名,sqlite的结果和mysql 可能不一样) -- 1、查询最大薪资值 SELECT MAX (`salary`) FROM `salaries` WHERE `to_date` = '9999-01-01' -- 2、查询第二大的薪资值 SELECT MAX (`salary`) FROM `salaries` WHERE `to_date` = '9999-01-01' AND `salary` < ( SELECT MAX (`salary`) FROM `salaries` WHERE `to_date` = '9999-01-01' ) -- 3、联表查询 SELECT e.emp_no, s.salary, e.last_name, e.first_name FROM employees AS e LEFT JOIN salaries AS s ON e.emp_no = s.emp_no WHERE s.salary = ( SELECT MAX (`salary`) FROM `salaries` WHERE `to_date` = '9999-01-01' AND `salary` < ( SELECT MAX (`salary`) FROM `salaries` WHERE `to_date` = '9999-01-01' ) ) |
对所有员工的薪水按照salary降序进行1-N的排名
所有员工的薪水按照salary降序先进行1-N的排名,如果salary相同,再按照emp_no升序排列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | drop table if exists `salaries` ; CREATE TABLE `salaries` ( `emp_no` int (11) NOT NULL , `salary` int (11) NOT NULL , `from_date` date NOT NULL , `to_date` date NOT NULL , PRIMARY KEY (`emp_no`,`from_date`)); INSERT INTO salaries VALUES (10001,88958, '2002-06-22' , '9999-01-01' ); INSERT INTO salaries VALUES (10002,72527, '2001-08-02' , '9999-01-01' ); INSERT INTO salaries VALUES (10003,43311, '2001-12-01' , '9999-01-01' ); INSERT INTO salaries VALUES (10004,72527, '2001-12-01' , '9999-01-01' ); -- MYSQL8版本支持 SELECT emp_no, salary, dense_rank ( ) over ( ORDER BY salary DESC ) AS rank FROM salaries WHERE to_date = '9999-01-01' ORDER BY rank ASC , emp_no ASC ; -- MYSQL5支持 rank排名:查询表中大于自己薪水的员工的数量(考虑并列:去重) SELECT s1.emp_no, s1.salary, ( SELECT COUNT ( DISTINCT s2.salary) FROM salaries s2 WHERE s2.to_date = '9999-01-01' AND s2.salary >= s1.salary) AS `rank` -- 去重:计算并列排名 FROM salaries s1 WHERE s1.to_date = '9999-01-01' ORDER BY s1.salary DESC , s1.emp_no ; |
获取所有非manager员工当前的薪水情况
获取所有非manager员工薪水情况,给出dept_no、emp_no以及salary
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | drop table if exists `dept_emp` ; drop table if exists `dept_manager` ; drop table if exists `employees` ; drop table if exists `salaries` ; CREATE TABLE `dept_emp` ( `emp_no` int (11) NOT NULL , `dept_no` char (4) NOT NULL , `from_date` date NOT NULL , `to_date` date NOT NULL , PRIMARY KEY (`emp_no`,`dept_no`)); CREATE TABLE `dept_manager` ( `dept_no` char (4) NOT NULL , `emp_no` int (11) NOT NULL , `from_date` date NOT NULL , `to_date` date NOT NULL , PRIMARY KEY (`emp_no`,`dept_no`)); CREATE TABLE `employees` ( `emp_no` int (11) NOT NULL , `birth_date` date NOT NULL , `first_name` varchar (14) NOT NULL , `last_name` varchar (16) NOT NULL , `gender` char (1) NOT NULL , `hire_date` date NOT NULL , PRIMARY KEY (`emp_no`)); CREATE TABLE `salaries` ( `emp_no` int (11) NOT NULL , `salary` int (11) NOT NULL , `from_date` date NOT NULL , `to_date` date NOT NULL , PRIMARY KEY (`emp_no`,`from_date`)); INSERT INTO dept_emp VALUES (10001, 'd001' , '1986-06-26' , '9999-01-01' ); INSERT INTO dept_emp VALUES (10002, 'd001' , '1996-08-03' , '9999-01-01' ); INSERT INTO dept_manager VALUES ( 'd001' ,10002, '1996-08-03' , '9999-01-01' ); INSERT INTO employees VALUES (10001, '1953-09-02' , 'Georgi' , 'Facello' , 'M' , '1986-06-26' ); INSERT INTO employees VALUES (10002, '1964-06-02' , 'Bezalel' , 'Simmel' , 'F' , '1996-08-03' ); INSERT INTO salaries VALUES (10001,88958, '1986-06-26' , '9999-01-01' ); INSERT INTO salaries VALUES (10002,72527, '1996-08-03' , '9999-01-01' ); -- 4表连接 SELECT D.dept_no, E.emp_no, S.salary FROM employees AS E LEFT JOIN dept_manager AS MGR ON E.emp_no = MGR.emp_no LEFT JOIN salaries AS S ON E.emp_no = S.emp_no LEFT JOIN dept_emp AS D ON E.emp_no = D.emp_no WHERE MGR.dept_no IS NULL |
获取有奖金的员工相关信息。
其中bonus类型btype为1其奖金为薪水salary的10%,btype为2其奖金为薪水的20%,其他类型均为薪水的30%。
to_date='9999-01-01'表示当前薪水。
请你给出emp_no、first_name、last_name、奖金类型btype、对应的当前薪水情况salary以及奖金金额bonus。
bonus结果保留一位小数,输出结果按emp_no升序排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | drop table if exists `employees` ; drop table if exists emp_bonus; drop table if exists `salaries` ; CREATE TABLE `employees` ( `emp_no` int (11) NOT NULL , `birth_date` date NOT NULL , `first_name` varchar (14) NOT NULL , `last_name` varchar (16) NOT NULL , `gender` char (1) NOT NULL , `hire_date` date NOT NULL , PRIMARY KEY (`emp_no`)); create table emp_bonus( emp_no int not null , recevied datetime not null , btype smallint not null ); CREATE TABLE `salaries` ( `emp_no` int (11) NOT NULL , `salary` int (11) NOT NULL , `from_date` date NOT NULL , `to_date` date NOT NULL , PRIMARY KEY (`emp_no`,`from_date`)); insert into emp_bonus values (10001, '2010-01-01' ,1), (10002, '2010-10-01' ,2); INSERT INTO employees VALUES (10001, '1953-09-02' , 'Georgi' , 'Facello' , 'M' , '1986-06-26' ); INSERT INTO employees VALUES (10002, '1964-06-02' , 'Bezalel' , 'Simmel' , 'F' , '1985-11-21' ); INSERT INTO salaries VALUES (10001,60117, '1986-06-26' , '1987-06-26' ); INSERT INTO salaries VALUES (10001,62102, '1987-06-26' , '1988-06-25' ); INSERT INTO salaries VALUES (10001,66074, '1988-06-25' , '1989-06-25' ); INSERT INTO salaries VALUES (10001,66596, '1989-06-25' , '1990-06-25' ); INSERT INTO salaries VALUES (10001,66961, '1990-06-25' , '1991-06-25' ); INSERT INTO salaries VALUES (10001,71046, '1991-06-25' , '1992-06-24' ); INSERT INTO salaries VALUES (10001,74333, '1992-06-24' , '1993-06-24' ); INSERT INTO salaries VALUES (10001,75286, '1993-06-24' , '1994-06-24' ); INSERT INTO salaries VALUES (10001,75994, '1994-06-24' , '1995-06-24' ); INSERT INTO salaries VALUES (10001,76884, '1995-06-24' , '1996-06-23' ); INSERT INTO salaries VALUES (10001,80013, '1996-06-23' , '1997-06-23' ); INSERT INTO salaries VALUES (10001,81025, '1997-06-23' , '1998-06-23' ); INSERT INTO salaries VALUES (10001,81097, '1998-06-23' , '1999-06-23' ); INSERT INTO salaries VALUES (10001,84917, '1999-06-23' , '2000-06-22' ); INSERT INTO salaries VALUES (10001,85112, '2000-06-22' , '2001-06-22' ); INSERT INTO salaries VALUES (10001,85097, '2001-06-22' , '2002-06-22' ); INSERT INTO salaries VALUES (10001,88958, '2002-06-22' , '9999-01-01' ); INSERT INTO salaries VALUES (10002,72527, '1996-08-03' , '1997-08-03' ); INSERT INTO salaries VALUES (10002,72527, '1997-08-03' , '1998-08-03' ); INSERT INTO salaries VALUES (10002,72527, '1998-08-03' , '1999-08-03' ); INSERT INTO salaries VALUES (10002,72527, '1999-08-03' , '2000-08-02' ); INSERT INTO salaries VALUES (10002,72527, '2000-08-02' , '2001-08-02' ); INSERT INTO salaries VALUES (10002,72527, '2001-08-02' , '9999-01-01' ); -- 主要是考察CASE WHEN 语法 SELECT E.emp_no, E.first_name, E.last_name, B.btype, S.salary, ( CASE B.btype WHEN 1 THEN ROUND(S.salary * 0.1, 4) WHEN 2 THEN ROUND(S.salary * 0.2, 4) ELSE ROUND(S.salary * 0.3, 4) END ) AS bonus FROM employees AS E LEFT JOIN salaries AS S ON E.emp_no = S.emp_no LEFT JOIN emp_bonus AS B ON E.emp_no = B.emp_no WHERE S.to_date = '9999-01-01' ORDER BY E.emp_no ASC |
统计salary的累计和running_total
按照salary的累计和running_total,
其中running_total为前N个当前( to_date = '9999-01-01')员工的salary累计和,其他以此类推。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | drop table if exists `salaries` ; CREATE TABLE `salaries` ( `emp_no` int (11) NOT NULL , `salary` int (11) NOT NULL , `from_date` date NOT NULL , `to_date` date NOT NULL , PRIMARY KEY (`emp_no`,`from_date`)); INSERT INTO salaries VALUES (10001,60117, '1986-06-26' , '1987-06-26' ); INSERT INTO salaries VALUES (10001,62102, '1987-06-26' , '1988-06-25' ); INSERT INTO salaries VALUES (10001,66074, '1988-06-25' , '1989-06-25' ); INSERT INTO salaries VALUES (10001,66596, '1989-06-25' , '1990-06-25' ); INSERT INTO salaries VALUES (10001,66961, '1990-06-25' , '1991-06-25' ); INSERT INTO salaries VALUES (10001,71046, '1991-06-25' , '1992-06-24' ); INSERT INTO salaries VALUES (10001,74333, '1992-06-24' , '1993-06-24' ); INSERT INTO salaries VALUES (10001,75286, '1993-06-24' , '1994-06-24' ); INSERT INTO salaries VALUES (10001,75994, '1994-06-24' , '1995-06-24' ); INSERT INTO salaries VALUES (10001,76884, '1995-06-24' , '1996-06-23' ); INSERT INTO salaries VALUES (10001,80013, '1996-06-23' , '1997-06-23' ); INSERT INTO salaries VALUES (10001,81025, '1997-06-23' , '1998-06-23' ); INSERT INTO salaries VALUES (10001,81097, '1998-06-23' , '1999-06-23' ); INSERT INTO salaries VALUES (10001,84917, '1999-06-23' , '2000-06-22' ); INSERT INTO salaries VALUES (10001,85112, '2000-06-22' , '2001-06-22' ); INSERT INTO salaries VALUES (10001,85097, '2001-06-22' , '2002-06-22' ); INSERT INTO salaries VALUES (10001,88958, '2002-06-22' , '9999-01-01' ); INSERT INTO salaries VALUES (10002,72527, '1996-08-03' , '1997-08-03' ); INSERT INTO salaries VALUES (10002,72527, '1997-08-03' , '1998-08-03' ); INSERT INTO salaries VALUES (10002,72527, '1998-08-03' , '1999-08-03' ); INSERT INTO salaries VALUES (10002,72527, '1999-08-03' , '2000-08-02' ); INSERT INTO salaries VALUES (10002,72527, '2000-08-02' , '2001-08-02' ); INSERT INTO salaries VALUES (10002,72527, '2001-08-02' , '9999-01-01' ); INSERT INTO salaries VALUES (10003,40006, '1995-12-03' , '1996-12-02' ); INSERT INTO salaries VALUES (10003,43616, '1996-12-02' , '1997-12-02' ); INSERT INTO salaries VALUES (10003,43466, '1997-12-02' , '1998-12-02' ); INSERT INTO salaries VALUES (10003,43636, '1998-12-02' , '1999-12-02' ); INSERT INTO salaries VALUES (10003,43478, '1999-12-02' , '2000-12-01' ); INSERT INTO salaries VALUES (10003,43699, '2000-12-01' , '2001-12-01' ); INSERT INTO salaries VALUES (10003,43311, '2001-12-01' , '9999-01-01' ); -- 查询running_total为前N个当前( to_date = '9999-01-01')员工的salary累计 SELECT s1.emp_no, s1.salary, ( SELECT SUM ( s2.salary ) FROM salaries AS s2 WHERE s2.emp_no <= s1.emp_no AND s2.to_date = '9999-01-01' ) AS running_total FROM salaries AS s1 WHERE s1.to_date = '9999-01-01' ORDER BY s1.emp_no |
给出employees表中排名为奇数行的first_name
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | drop table if exists `employees` ; CREATE TABLE `employees` ( `emp_no` int (11) NOT NULL , `birth_date` date NOT NULL , `first_name` varchar (14) NOT NULL , `last_name` varchar (16) NOT NULL , `gender` char (1) NOT NULL , `hire_date` date NOT NULL , PRIMARY KEY (`emp_no`)); INSERT INTO employees VALUES (10001, '1953-09-02' , 'Georgi' , 'Facello' , 'M' , '1986-06-26' ); INSERT INTO employees VALUES (10002, '1964-06-02' , 'Bezalel' , 'Simmel' , 'F' , '1985-11-21' ); INSERT INTO employees VALUES (10005, '1955-01-21' , 'Kyoichi' , 'Maliniak' , 'M' , '1989-09-12' ); INSERT INTO employees VALUES (10006, '1953-04-20' , 'Anneke' , 'Preusig' , 'F' , '1989-06-02' ); -- 主要实现SQL1 - MYSQL8开窗函数实现 SELECT first_name, row_number ( ) over ( ORDER BY first_name ) AS rank_num FROM employees -- 主要实现SQL1 - 不使用MYSQL8开窗函数,设置变量实现 SET @orderId = 0; SELECT first_name, @orderId:= @orderId + 1 AS `rank` FROM `employees` ORDER BY first_name -- 解决SQL: SELECT E.first_name FROM employees AS E JOIN ( -- 上面两种SQL任选一种作为联表查询 ) AS E2 ON E.first_name = E2.first_name WHERE E2.`rank` % 2 = 1; -- 直接子查询嵌套会因为不是原表顺序,答案不符合 SELECT e.first_name FROM employees e JOIN ( SELECT first_name, ROW_NUMBER() OVER( ORDER BY first_name ASC ) AS r_num FROM employees ) AS t ON e.first_name = t.first_name WHERE t.r_num % 2 = 1; |
异常的邮件概率
每一个日期里面,正常用户发送给正常用户邮件失败的概率是多少,
结果保留到小数点后面3位(3位之后的四舍五入),并且按照日期升序排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | drop table if exists email; drop table if exists user ; CREATE TABLE `email` ( `id` int (4) NOT NULL , `send_id` int (4) NOT NULL , `receive_id` int (4) NOT NULL , `type` varchar (32) NOT NULL , ` date ` date NOT NULL , PRIMARY KEY (`id`)); CREATE TABLE ` user ` ( `id` int (4) NOT NULL , `is_blacklist` int (4) NOT NULL , PRIMARY KEY (`id`)); INSERT INTO email VALUES (1,2,3, 'completed' , '2020-01-11' ), (2,1,3, 'completed' , '2020-01-11' ), (3,1,4, 'no_completed' , '2020-01-11' ), (4,3,1, 'completed' , '2020-01-12' ), (5,3,4, 'completed' , '2020-01-12' ), (6,4,1, 'completed' , '2020-01-12' ); INSERT INTO user VALUES (1,0), (2,1), (3,0), (4,0); -- 1、联表实现筛选白名单用户 SELECT `email`.* FROM `email` JOIN ` user ` AS u1 ON ( email.send_id = u1.id AND u1.is_blacklist = 0 ) JOIN ` user ` AS u2 ON ( email.receive_id = u2.id AND u2.is_blacklist = 0 ) -- 2、子查询实现筛选 -- 查询黑名单用户,或者正常用户 SELECT id FROM ` user ` WHERE `is_blacklist` = 1 -- 在EMAIL表中筛选正常用户来往的邮件记录 SELECT `email`.* FROM `email` WHERE email.send_id NOT IN ( SELECT id FROM ` user ` WHERE `is_blacklist` = 1) AND email.receive_id NOT IN ( SELECT id FROM ` user ` WHERE `is_blacklist` = 1) -- 3、按日期分组进行筛选,直接计数异常次数和总次数即可实现 SELECT `email`. date , SUM (`email`.type = 'no_completed' ) AS `异常次数`, COUNT (`email`.type) AS `总计次数`, ROUND ( SUM (`email`.type = 'no_completed' ) * 1.0 / COUNT (`email`.type), 3 ) AS `概率` FROM `email` WHERE email.send_id NOT IN ( SELECT id FROM ` user ` WHERE `is_blacklist` = 1) AND email.receive_id NOT IN ( SELECT id FROM ` user ` WHERE `is_blacklist` = 1) GROUP BY `email`. date ORDER BY `email`. date -- 最终SQL SELECT `email`. date , ROUND ( SUM (`email`.type = 'no_completed' ) * 1.0 / COUNT (`email`.type), 3 ) AS `p` FROM `email` WHERE email.send_id NOT IN ( SELECT id FROM ` user ` WHERE `is_blacklist` = 1) AND email.receive_id NOT IN ( SELECT id FROM ` user ` WHERE `is_blacklist` = 1) GROUP BY `email`. date ORDER BY `email`. date -- 或者按非异常次数查询 SELECT `email`. date , SUM ( CASE `email`.type WHEN 'completed' THEN 0 ELSE 1 END ) AS `总计`, COUNT (`email`.type) AS `次数`, ROUND ( SUM ( CASE `email`.type WHEN 'completed' THEN 0 ELSE 1 END ) * 1.0 / COUNT (`email`.type), 3 ) AS `概率` FROM `email` WHERE email.send_id NOT IN ( SELECT id FROM ` user ` WHERE `is_blacklist` = 1) AND email.receive_id NOT IN ( SELECT id FROM ` user ` WHERE `is_blacklist` = 1) GROUP BY `email`. date ORDER BY `email`. date |
牛客每个人最近的登录日期(二)
查询每个用户最近一天登录的日子,用户的名字,以及用户用的设备的名字,
并且查询结果按照user的name升序排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | drop table if exists login; drop table if exists user ; drop table if exists client; CREATE TABLE `login` ( `id` int (4) NOT NULL , `user_id` int (4) NOT NULL , `client_id` int (4) NOT NULL , ` date ` date NOT NULL , PRIMARY KEY (`id`)); CREATE TABLE ` user ` ( `id` int (4) NOT NULL , ` name ` varchar (32) NOT NULL , PRIMARY KEY (`id`)); CREATE TABLE `client` ( `id` int (4) NOT NULL , ` name ` varchar (32) NOT NULL , PRIMARY KEY (`id`)); INSERT INTO login VALUES (1,2,1, '2020-10-12' ), (2,3,2, '2020-10-12' ), (3,2,2, '2020-10-13' ), (4,3,2, '2020-10-13' ); INSERT INTO user VALUES (1, 'tm' ), (2, 'fh' ), (3, 'wangchao' ); INSERT INTO client VALUES (1, 'pc' ), (2, 'ios' ), (3, 'anroid' ), (4, 'h5' ); -- 全部连接起来筛选最近日期 SELECT U.` name `, C.` name ` AS `client`, L.` date ` FROM ` user ` AS U JOIN login AS L ON U.id = L.user_id JOIN client AS C ON L.client_id = C.id WHERE L.` date ` = ( SELECT MAX ( date ) FROM login) ORDER BY U.` name ` ASC |
牛客每个人最近的登录日期(三)
查询新登录用户次日成功的留存率,即第1天登陆之后,第2天再次登陆的概率,保存小数点后面3位(3位之后的四舍五入)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | drop table if exists login; CREATE TABLE `login` ( `id` int (4) NOT NULL , `user_id` int (4) NOT NULL , `client_id` int (4) NOT NULL , ` date ` date NOT NULL , PRIMARY KEY (`id`)); INSERT INTO login VALUES (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,4,1, '2020-10-13' ), (6,1,2, '2020-10-13' ), (7,1,2, '2020-10-14' ); SELECT round( count ( DISTINCT user_id ) * 1.0 / ( SELECT count ( DISTINCT user_id ) FROM login ), 3 ) AS `p` FROM login WHERE ( user_id, date ) IN ( SELECT user_id, DATE_ADD( min ( date ), INTERVAL 1 DAY ) FROM login GROUP BY user_id ); |
牛客每个人最近的登录日期(四)
查询每个日期登录新用户个数,并且查询结果按照日期升序排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | drop table if exists login; CREATE TABLE `login` ( `id` int (4) NOT NULL , `user_id` int (4) NOT NULL , `client_id` int (4) NOT NULL , ` date ` date NOT NULL , PRIMARY KEY (`id`)); INSERT INTO login VALUES (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' ); -- 拿到首次登录用户和时间 SELECT `user_id`, MIN ( ` date ` ) FROM `login` GROUP BY user_id -- 1、可以对Login表的日期分组,用户和日期可以用IN和上述查询结果进行匹配处理 -- 2、如果匹配成功,表示这个用户是在这个日期是首次登录 -- 3、ELSE NULL 不能写 ELSE 0,因为0就会算一条记录,NULL则不被COUNT函数计数 SELECT ` date `, COUNT ( DISTINCT CASE WHEN ( user_id, date ) IN ( SELECT user_id, min ( date ) FROM login GROUP BY user_id ) THEN `user_id` ELSE NULL END ) AS `new` FROM login GROUP BY ` date ` ORDER BY ` date ` ASC ; |
牛客每个人最近的登录日期(六)
查询刷题信息,包括: 用户的名字,以及截止到某天,累计总共通过了多少题,
并且查询结果先按照日期升序排序,再按照姓名升序排序,有登录却没有刷题的哪一天的数据不需要输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | drop table if exists login; drop table if exists passing_number; drop table if exists user ; drop table if exists client; CREATE TABLE `login` ( `id` int (4) NOT NULL , `user_id` int (4) NOT NULL , `client_id` int (4) NOT NULL , ` date ` date NOT NULL , PRIMARY KEY (`id`)); CREATE TABLE `passing_number` ( `id` int (4) NOT NULL , `user_id` int (4) NOT NULL , `number` int (4) NOT NULL , ` date ` date NOT NULL , PRIMARY KEY (`id`)); CREATE TABLE ` user ` ( `id` int (4) NOT NULL , ` name ` varchar (32) NOT NULL , PRIMARY KEY (`id`)); INSERT INTO login VALUES (1,2,1, '2020-10-12' ), (2,3,2, '2020-10-12' ), (3,1,2, '2020-10-12' ), (4,1,3, '2020-10-13' ), (5,3,2, '2020-10-13' ); INSERT INTO passing_number VALUES (1,2,4, '2020-10-12' ), (2,3,1, '2020-10-12' ), (3,1,0, '2020-10-13' ), (4,3,2, '2020-10-13' ); INSERT INTO user VALUES (1, 'tm' ), (2, 'fh' ), (3, 'wangchao' ); -- 1、使用开窗函数 SELECT ` name ` AS `u_n`, ` date `, SUM (number) OVER (PARTITION BY `user_id` ORDER BY date ) AS `ps_num` FROM `passing_number` AS `p` INNER JOIN ` user ` ON ` user `.`id` = `p`.`user_id` GROUP BY ` date `, `u_n` ORDER BY ` date `, ` name ` -- 2、自连接实现 SELECT ` name ` AS u_n, date , p.ps_num FROM ( SELECT p1.user_id, p1. date , SUM (p2.number) AS ps_num FROM passing_number AS p1, passing_number AS p2 WHERE p1. date >= p2. date AND p1.user_id = p2.user_id GROUP BY p1. date ,p1.user_id ) AS p JOIN ` user ` ON ` user `.id = p.`user_id` ORDER BY p. date , ` user `.` name ` |
考试分数(三)
找出每个岗位分数排名前2名的用户,得到的结果先按照language的name升序排序,再按照积分降序排序,最后按照grade的id升序排序
完全理解不了解题思路了已经。。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | drop table if exists grade; drop table if exists language; CREATE TABLE `grade` ( `id` int (4) NOT NULL , `language_id` int (4) NOT NULL , `score` int (4) NOT NULL , PRIMARY KEY (`id`)); CREATE TABLE `language` ( `id` int (4) NOT NULL , ` name ` varchar (32) NOT NULL , PRIMARY KEY (`id`)); INSERT INTO grade VALUES (1,1,12000), (2,1,13000), (3,2,11000), (4,2,10000), (5,3,11000), (6,1,11000), (7,2,11000); INSERT INTO language VALUES (1, 'C++' ), (2, 'JAVA' ), (3, 'Python' ); SELECT g1.id, l. NAME , g1.score FROM grade g1 JOIN `language` l ON g1.language_id = l.id WHERE ( SELECT count ( DISTINCT g2.score ) FROM grade g2 WHERE g2.score >= g1.score AND g1.language_id = g2.language_id ) <= 2 ORDER BY l. NAME , g1.score DESC , g1.id; |
考试分数(四)
查询各个岗位分数升序排列之后的中位数位置的范围,并且按job升序排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | drop table if exists grade; CREATE TABLE grade( `id` int (4) NOT NULL , `job` varchar (32) NOT NULL , `score` int (10) NOT NULL , PRIMARY KEY (`id`)); INSERT INTO grade VALUES (1, 'C++' ,11001), (2, 'C++' ,10000), (3, 'C++' ,9000), (4, 'Java' ,12000), (5, 'Java' ,13000), (6, 'B' ,12000), (7, 'B' ,11000), (8, 'B' ,9999); -- 题解 SELECT job, FLOOR( ( COUNT (1) + 1) / 2) AS 'start' , CEIL( ( COUNT (1) + 1) / 2) AS 'end' FROM grade GROUP BY job ORDER BY job; + ------+-------+-----+ | job | start | end | + ------+-------+-----+ | B | 2 | 2 | | C++ | 2 | 2 | | Java | 1 | 2 | + ------+-------+-----+ 3 rows in set (0.05 sec) |
牛客的课程订单分析(四)
查询在2025-10-15以后,如果有一个用户下单2个以及2个以上状态为购买成功的C++课程或Java课程或Python课程,那么输出这个用户的user_id,以及满足前面条件的第一次购买成功的C++课程或Java课程或Python课程的日期first_buy_date,以及所有日期里购买成功的C++课程或Java课程或Python课程的次数cnt,并且输出结果按照user_id升序排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | drop table if exists order_info; CREATE TABLE order_info ( id int (4) NOT NULL , user_id int (11) NOT NULL , product_name varchar (256) NOT NULL , status varchar (32) NOT NULL , client_id int (4) NOT NULL , date date NOT NULL , PRIMARY KEY (id)); INSERT INTO order_info VALUES (1,557336, 'C++' , 'no_completed' ,1, '2025-10-10' ), (2,230173543, 'Python' , 'completed' ,2, '2025-10-12' ), (3,57, 'JS' , 'completed' ,3, '2025-10-23' ), (4,57, 'C++' , 'completed' ,3, '2025-10-23' ), (5,557336, 'Java' , 'completed' ,1, '2025-10-23' ), (6,57, 'Java' , 'completed' ,1, '2025-10-24' ), (7,557336, 'C++' , 'completed' ,1, '2025-10-25' ), (8,557336, 'Python' , 'completed' ,1, '2025-10-25' ); -- 直接分组之后筛选对应条件,取MIN(date) 和 COUNT(product_name) SELECT user_id, MIN ( date ) AS `first_buy_date`, COUNT (product_name) AS `cnt` FROM order_info WHERE date > '2025-10-15' AND STATUS = 'completed' AND product_name IN ( 'C++' , 'Java' , 'Python' ) GROUP BY user_id HAVING COUNT ( user_id ) > 1 ; + ---------+----------------+-----+ | user_id | first_buy_date | cnt | + ---------+----------------+-----+ | 57 | 2025-10-23 | 2 | | 557336 | 2025-10-23 | 3 | + ---------+----------------+-----+ 2 rows in set (0.05 sec) |
牛客的课程订单分析(七)
查询在2025-10-15以后,同一个用户下单2个以及2个以上状态为购买成功的C++课程或Java课程或Python课程的来源信息,
第一列是显示的是客户端名字,如果是拼团订单则显示GroupBuy,第二列显示这个客户端(或者是拼团订单)有多少订单,
最后结果按照第一列(source)升序排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | drop table if exists order_info; drop table if exists client; CREATE TABLE order_info ( id int (4) NOT NULL , user_id int (11) NOT NULL , product_name varchar (256) NOT NULL , status varchar (32) NOT NULL , client_id int (4) NOT NULL , date date NOT NULL , is_group_buy varchar (32) NOT NULL , PRIMARY KEY (id)); CREATE TABLE client( id int (4) NOT NULL , name varchar (32) NOT NULL , PRIMARY KEY (id) ); INSERT INTO order_info VALUES (1,557336, 'C++' , 'no_completed' ,1, '2025-10-10' , 'No' ), (2,230173543, 'Python' , 'completed' ,2, '2025-10-12' , 'No' ), (3,57, 'JS' , 'completed' ,0, '2025-10-23' , 'Yes' ), (4,57, 'C++' , 'completed' ,3, '2025-10-23' , 'No' ), (5,557336, 'Java' , 'completed' ,0, '2025-10-23' , 'Yes' ), (6,57, 'Java' , 'completed' ,1, '2025-10-24' , 'No' ), (7,557336, 'C++' , 'completed' ,0, '2025-10-25' , 'Yes' ); INSERT INTO client VALUES (1, 'PC' ), (2, 'Android' ), (3, 'IOS' ), (4, 'H5' ); -- SELECT IF(a.client_id = 0, 'GroupBuy' ,c. name ) AS source, COUNT (*) AS cnt FROM ( SELECT client_id FROM order_info WHERE date > '2025-10-15' AND STATUS = 'completed' AND product_name IN ( 'C++' , 'Java' , 'Python' ) AND user_id IN ( SELECT user_id FROM order_info WHERE STATUS = 'completed' GROUP BY user_id HAVING COUNT ( * ) >= 2 ) ) AS a LEFT JOIN client c ON a.client_id = c.id GROUP BY a.client_id ORDER BY source |
最差是第几名(二)
查询一下,如果只有1个中位数,输出1个,如果有2个中位数,按grade升序输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | drop table if exists class_grade; CREATE TABLE class_grade ( grade varchar (32) NOT NULL , number int (4) NOT NULL ); INSERT INTO class_grade VALUES ( 'A' ,2), ( 'C' ,4), ( 'B' ,4), ( 'D' ,2); -- 题解 SELECT grade FROM ( SELECT grade, ( SELECT SUM (number) FROM class_grade c1 WHERE c1.grade < c2.grade ) AS s, ( SELECT SUM (number) FROM class_grade c1 WHERE c1.grade <= c2.grade ) AS e FROM class_grade c2 ORDER BY grade ) AS t1, ( SELECT sum ( number ) AS sums FROM class_grade ) AS t2 WHERE ( sums / 2 ) BETWEEN s AND e |
获得积分最多的人
查找积分增加最高的用户的id(可能有多个),名字,以及他的总积分是多少,查询结果按照id升序排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | drop table if exists user ; drop table if exists grade_info; CREATE TABLE user ( id int (4) NOT NULL , name varchar (32) NOT NULL ); CREATE TABLE grade_info ( user_id int (4) NOT NULL , grade_num int (4) NOT NULL , type varchar (32) NOT NULL ); INSERT INTO user VALUES (1, 'tm' ), (2, 'wwy' ), (3, 'zk' ), (4, 'qq' ), (5, 'lm' ); INSERT INTO grade_info VALUES (1,3, 'add' ), (2,3, 'add' ), (1,1, 'add' ), (3,3, 'add' ), (4,3, 'add' ), (5,3, 'add' ), (3,1, 'add' ); -- 1、获取所有人积分 SELECT `user_id`, SUM (`grade_num`) AS `total` FROM grade_info WHERE `type` = 'add' GROUP BY `user_id` ORDER BY `total` DESC -- 2、获取积分最大值 SELECT SUM (`grade_num`) AS `grade_sum` FROM grade_info WHERE `type` = 'add' GROUP BY user_id ORDER BY `grade_sum` DESC LIMIT 1 -- 3、子查询筛选符合的用户 SELECT `user_id`, SUM (`grade_num`) AS `total` FROM grade_info WHERE `type` = 'add' GROUP BY `user_id` HAVING `total` = ( SELECT SUM (`grade_num`) AS `grade_sum` FROM grade_info WHERE `type` = 'add' GROUP BY user_id ORDER BY `grade_sum` DESC LIMIT 1 ) ORDER BY `total` DESC , `user_id` ASC -- 最终解题SQL SELECT ` user `.` name `, `main`.`total` FROM ( SELECT `user_id`, SUM (`grade_num`) AS `total` FROM grade_info WHERE `type` = 'add' GROUP BY `user_id` HAVING `total` = ( SELECT SUM (`grade_num`) AS `grade_sum` FROM grade_info WHERE `type` = 'add' GROUP BY user_id ORDER BY `grade_sum` DESC LIMIT 1 ) ORDER BY `total` DESC , `user_id` ASC ) AS `main` JOIN ` user ` ON `main`.`user_id` = ` user `.`id` |
网易云音乐推荐(网易校招笔试真题)
查询向user_id = 1 的用户,推荐其关注的人喜欢的音乐。
不要推荐该用户已经喜欢的音乐,并且按music的id升序排列。你返回的结果中不应当包含重复项
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | CREATE TABLE `follow` ( `user_id` int (4) NOT NULL , `follower_id` int (4) NOT NULL , PRIMARY KEY (`user_id`,`follower_id`)); CREATE TABLE `music_likes` ( `user_id` int (4) NOT NULL , `music_id` int (4) NOT NULL , PRIMARY KEY (`user_id`,`music_id`)); CREATE TABLE `music` ( `id` int (4) NOT NULL , `music_name` varchar (32) NOT NULL , PRIMARY KEY (`id`)); INSERT INTO follow VALUES (1,2); INSERT INTO follow VALUES (1,4); INSERT INTO follow VALUES (2,3); INSERT INTO music_likes VALUES (1,17); INSERT INTO music_likes VALUES (2,18); INSERT INTO music_likes VALUES (2,19); INSERT INTO music_likes VALUES (3,20); INSERT INTO music_likes VALUES (4,17); INSERT INTO music VALUES (17, 'yueyawang' ); INSERT INTO music VALUES (18, 'kong' ); INSERT INTO music VALUES (19, 'MOM' ); INSERT INTO music VALUES (20, 'Sold Out' ); -- ID为1的用户的关注人 SELECT `follower_id` FROM follow WHERE `user_id` = 1 -- ID为1的用户 喜欢的音乐 SELECT music_id FROM music_likes WHERE `user_id` = 1 -- 关注的人喜欢的音乐 SELECT music_id FROM music_likes WHERE `user_id` IN ( SELECT `follower_id` FROM follow WHERE `user_id` = 1 ) -- 去掉用户自己的音乐, 就是题目需要的歌曲了 SELECT music_id FROM music_likes WHERE `user_id` IN ( SELECT `follower_id` FROM follow WHERE `user_id` = 1 ) AND music_id NOT IN ( SELECT music_id FROM music_likes WHERE `user_id` = 1 ) -- 联表得出最终结果 SELECT music.`music_name` FROM ( SELECT music_id FROM music_likes WHERE `user_id` IN ( SELECT `follower_id` FROM follow WHERE `user_id` = 1 ) AND music_id NOT IN ( SELECT music_id FROM music_likes WHERE `user_id` = 1 ) ) AS `main` JOIN `music` ON `main`.music_id = `music`.id ORDER BY `music`.id ASC |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· 地球OL攻略 —— 某应届生求职总结
2020-06-07 【Java】【设计模式 Design Pattern】迭代器模式 Iterator/Cursor
2020-06-07 【Java】【设计模式 Design Pattern】命令模式 Command