当前位置:网站首页>数据库系统原理与应用教程(074)—— MySQL 练习题:操作题 141-150(十八):综合练习
数据库系统原理与应用教程(074)—— MySQL 练习题:操作题 141-150(十八):综合练习
2022-08-03 11:55:00 【睿思达DBA_WGX】
数据库系统原理与应用教程(074)—— MySQL 练习题:操作题 141-150(十八):综合练习
141、求名次(1)
该题目使用的表和数据如下:
/* 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'); */
数据表:salaries,表中数据如下:
mysql> select * from salaries;
+--------+--------+------------+------------+
| emp_no | salary | from_date | to_date |
+--------+--------+------------+------------+
| 10001 | 60117 | 1986-06-26 | 1987-06-26 |
| 10001 | 62102 | 1987-06-26 | 1988-06-25 |
| 10001 | 66074 | 1988-06-25 | 1989-06-25 |
| 10001 | 66596 | 1989-06-25 | 1990-06-25 |
| 10001 | 66961 | 1990-06-25 | 1991-06-25 |
| 10001 | 71046 | 1991-06-25 | 1992-06-24 |
| 10001 | 74333 | 1992-06-24 | 1993-06-24 |
| 10001 | 75286 | 1993-06-24 | 1994-06-24 |
| 10001 | 75994 | 1994-06-24 | 1995-06-24 |
| 10001 | 76884 | 1995-06-24 | 1996-06-23 |
| 10001 | 80013 | 1996-06-23 | 1997-06-23 |
| 10001 | 81025 | 1997-06-23 | 1998-06-23 |
| 10001 | 81097 | 1998-06-23 | 1999-06-23 |
| 10001 | 84917 | 1999-06-23 | 2000-06-22 |
| 10001 | 85112 | 2000-06-22 | 2001-06-22 |
| 10001 | 85097 | 2001-06-22 | 2002-06-22 |
| 10001 | 88958 | 2002-06-22 | 9999-01-01 |
| 10002 | 72527 | 1996-08-03 | 1997-08-03 |
| 10002 | 72527 | 1997-08-03 | 1998-08-03 |
| 10002 | 72527 | 1998-08-03 | 1999-08-03 |
| 10002 | 72527 | 1999-08-03 | 2000-08-02 |
| 10002 | 72527 | 2000-08-02 | 2001-08-02 |
| 10002 | 72527 | 2001-08-02 | 9999-01-01 |
| 10003 | 40006 | 1995-12-03 | 1996-12-02 |
| 10003 | 43616 | 1996-12-02 | 1997-12-02 |
| 10003 | 43466 | 1997-12-02 | 1998-12-02 |
| 10003 | 43636 | 1998-12-02 | 1999-12-02 |
| 10003 | 43478 | 1999-12-02 | 2000-12-01 |
| 10003 | 43699 | 2000-12-01 | 2001-12-01 |
| 10003 | 43311 | 2001-12-01 | 9999-01-01 |
+--------+--------+------------+------------+
30 rows in set (0.00 sec)
【问题】查询当前员工(to_date = ‘9999-01-01’)的 emp_no,salary,salary 的累计和 running_total(running_total 为前 N 个的 salary 累计和),查询结果如下:
emp_no | salary | running_total |
---|---|---|
10001 | 88958 | 88958 |
10002 | 72527 | 161485 |
10003 | 43311 | 204796 |
解答:
/* select emp_no, salary, @sum_salary := @sum_salary + salary running_total from salaries, (select @sum_salary := 0) a where to_date = '9999-01-01'; */
mysql> select emp_no, salary,
-> @sum_salary := @sum_salary + salary running_total
-> from salaries, (select @sum_salary := 0) a
-> where to_date = '9999-01-01';
+--------+--------+---------------+
| emp_no | salary | running_total |
+--------+--------+---------------+
| 10001 | 88958 | 88958 |
| 10002 | 72527 | 161485 |
| 10003 | 43311 | 204796 |
+--------+--------+---------------+
3 rows in set (0.00 sec)
/* select a.emp_no, a.salary, sum(b.salary) running_total from salaries a join salaries b on a.emp_no >= b.emp_no where a.to_date = '9999-01-01' and b.to_date = '9999-01-01' group by a.emp_no, a.salary; */
mysql> select a.emp_no, a.salary, sum(b.salary) running_total
-> from salaries a join salaries b on a.emp_no >= b.emp_no
-> where a.to_date = '9999-01-01' and b.to_date = '9999-01-01'
-> group by a.emp_no, a.salary;
+--------+--------+---------------+
| emp_no | salary | running_total |
+--------+--------+---------------+
| 10001 | 88958 | 88958 |
| 10002 | 72527 | 161485 |
| 10003 | 43311 | 204796 |
+--------+--------+---------------+
3 rows in set (0.00 sec)
142、求名次(2)
该题目使用的表和数据如下:
/* 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'); */
数据表:employees,表中数据如下:
mysql> select * from employees;
+--------+------------+------------+-----------+--------+------------+
| emp_no | birth_date | first_name | last_name | gender | hire_date |
+--------+------------+------------+-----------+--------+------------+
| 10001 | 1953-09-02 | Georgi | Facello | M | 1986-06-26 |
| 10002 | 1964-06-02 | Bezalel | Simmel | F | 1985-11-21 |
| 10005 | 1955-01-21 | Kyoichi | Maliniak | M | 1989-09-12 |
| 10006 | 1953-04-20 | Anneke | Preusig | F | 1989-06-02 |
+--------+------------+------------+-----------+--------+------------+
4 rows in set (0.00 sec)
【问题】查询 first_name 排名(按 first_name 升序排序)为奇数的 first_name,查询结果如下:
first |
---|
Anneke |
Georgi |
解答:
/* select a.first_name first from employees a join employees b on a.first_name >= b.first_name group by a.first_name having mod(count(*),2) = 1 order by a.first_name; */
mysql> select a.first_name first
-> from employees a join employees b on a.first_name >= b.first_name
-> group by a.first_name
-> having mod(count(*),2) = 1
-> order by a.first_name;
+--------+
| first |
+--------+
| Anneke |
| Georgi |
+--------+
2 rows in set (0.00 sec)
/* select first from (select first_name first, (select @rank := @rank + 1) rank from employees, (select @rank := 0) a order by first_name) b where mod(rank, 2) = 1 order by first; */
mysql> select first from
-> (select first_name first, (select @rank := @rank + 1) rank
-> from employees, (select @rank := 0) a
-> order by first_name) b
-> where mod(rank, 2) = 1
-> order by first;
+--------+
| first |
+--------+
| Anneke |
| Georgi |
+--------+
2 rows in set (0.00 sec)
143、分组查询
该题目使用的表和数据如下:
/* drop table if exists grade; CREATE TABLE `grade` ( `id` int(4) NOT NULL, `number` int(4) NOT NULL, PRIMARY KEY (`id`)); INSERT INTO grade VALUES (1,111), (2,333), (3,111), (4,111), (5,333); */
数据表:grade,表中数据如下:
mysql> select * from grade;
+----+--------+
| id | number |
+----+--------+
| 1 | 111 |
| 2 | 333 |
| 3 | 111 |
| 4 | 111 |
| 5 | 333 |
+----+--------+
5 rows in set (0.00 sec)
【问题】查询积分表中出现三次以及三次以上的积分,查询结果如下:
number_cnt |
---|
111 |
解答:
mysql> select number from grade group by number having count(*) >= 3;
+--------+
| number |
+--------+
| 111 |
+--------+
1 row in set (0.00 sec)
144、名次问题
该题目使用的表和数据如下:
/* drop table if exists passing_number; CREATE TABLE `passing_number` ( `id` int(4) NOT NULL, `number` int(4) NOT NULL, PRIMARY KEY (`id`)); INSERT INTO passing_number VALUES (1,4), (2,3), (3,3), (4,2), (6,4), (5,5); */
数据表:passing_number,表中数据如下:
mysql> select * from passing_number;
+----+--------+
| id | number |
+----+--------+
| 1 | 4 |
| 2 | 3 |
| 3 | 3 |
| 4 | 2 |
| 5 | 5 |
| 6 | 4 |
+----+--------+
6 rows in set (0.02 sec)
【问题】请根据上表,输出通过的题目的排名,通过题目个数相同的,排名相同,此时按照 id 升序排列,查询结果如下:
id | number | t_rank |
---|---|---|
5 | 5 | 1 |
1 | 4 | 2 |
6 | 4 | 2 |
2 | 3 | 3 |
3 | 3 | 3 |
4 | 2 | 4 |
解答:
/* select p.id, p.number, (select count(distinct number)+1 from passing_number where number > p.number) t_rank from passing_number p order by t_rank, p.id; */
mysql> select p.id, p.number,
-> (select count(distinct number)+1 from passing_number where number > p.number) t_rank
-> from passing_number p
-> order by t_rank, p.id;
+----+--------+--------+
| id | number | t_rank |
+----+--------+--------+
| 5 | 5 | 1 |
| 1 | 4 | 2 |
| 6 | 4 | 2 |
| 2 | 3 | 3 |
| 3 | 3 | 3 |
| 4 | 2 | 4 |
+----+--------+--------+
6 rows in set (0.00 sec)
/* select p.id, p.number, (select count(number)+1 from passing_number where number > p.number) t_rank from passing_number p order by t_rank, p.id; */
mysql> select p.id, p.number,
-> (select count(number)+1 from passing_number where number > p.number) t_rank
-> from passing_number p
-> order by t_rank, p.id;
+----+--------+--------+
| id | number | t_rank |
+----+--------+--------+
| 5 | 5 | 1 |
| 1 | 4 | 2 |
| 6 | 4 | 2 |
| 2 | 3 | 4 |
| 3 | 3 | 4 |
| 4 | 2 | 6 |
+----+--------+--------+
6 rows in set (0.00 sec)
145、外连接
该题目使用的表和数据如下:
/* drop table if exists person; drop table if exists task; CREATE TABLE `person` ( `id` int(4) NOT NULL, `name` varchar(32) NOT NULL, PRIMARY KEY (`id`)); CREATE TABLE `task` ( `id` int(4) NOT NULL, `person_id` int(4) NOT NULL, `content` varchar(32) NOT NULL, PRIMARY KEY (`id`)); INSERT INTO person VALUES (1,'fh'), (2,'tm'); INSERT INTO task VALUES (1,2,'tm works well'), (2,2,'tm works well'); */
person 表,主键为 id,表中数据如下:
mysql> select * from person;
+----+------+
| id | name |
+----+------+
| 1 | fh |
| 2 | tm |
+----+------+
2 rows in set (0.00 sec)
任务表:task,主键为id,表中数据如下:
mysql> select * from task;
+----+-----------+---------------+
| id | person_id | content |
+----+-----------+---------------+
| 1 | 2 | tm works well |
| 2 | 2 | tm works well |
+----+-----------+---------------+
2 rows in set (0.00 sec)
【问题】请查找每个人的任务情况并输出,没有任务的也要输出,输出结果按照 person 的 id 升序排序,查询结果如下:
id | name | content |
---|---|---|
1 | fh | NULL |
2 | tm | tm1 works well |
2 | tm | tm2 works well |
解答:
/* select p.id, p.name, t.content from person p left join task t on p.id = t.person_id order by p.id; */
mysql> select p.id, p.name, t.content
-> from person p left join task t on p.id = t.person_id
-> order by p.id;
+----+------+---------------+
| id | name | content |
+----+------+---------------+
| 1 | fh | NULL |
| 2 | tm | tm works well |
| 2 | tm | tm works well |
+----+------+---------------+
3 rows in set (0.03 sec)
146、子连接
该题目使用的表和数据如下:
/* 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); */
邮件表:email,id 为主键, type 是枚举类型,枚举成员为:completed,no_completed,completed 代表邮件发送是成功的,no_completed 代表邮件是发送失败的。表中数据如下:
mysql> select * from email;
+----+---------+------------+--------------+------------+
| id | send_id | receive_id | type | date |
+----+---------+------------+--------------+------------+
| 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 |
+----+---------+------------+--------------+------------+
6 rows in set (0.00 sec)
用户表:user,id 为主键(id 代表用户编号),is_blacklist 为 0 代表为正常用户,is_blacklist 为 1 代表为黑名单用户,表中数据如下::
ysql> select * from user;
+----+--------------+
| id | is_blacklist |
+----+--------------+
| 1 | 0 |
| 2 | 1 |
| 3 | 0 |
| 4 | 0 |
+----+--------------+
4 rows in set (0.00 sec)
【问题】请编写一个 SQL 查询,每一个日期里面,正常用户发送给正常用户邮件失败的概率是多少,结果保留到小数点后面 3 位(3 位之后的四舍五入),按照日期升序排序,查询结果如下:
date | p |
---|---|
2020-01-11 | 0.333 |
2020-01-12 | 0.000 |
解答:
/* select e.date, round(sum(if(send_id in (select id from user where is_blacklist = 0) and receive_id in (select id from user where is_blacklist = 0) and type = 'no_completed', 1, 0)) / count(*),3) p from email e group by e.date order by e.date; */
mysql> select e.date,
-> round(sum(if(send_id in (select id from user where is_blacklist = 0)
-> and receive_id in (select id from user where is_blacklist = 0)
-> and type = 'no_completed', 1, 0)) / count(*),3) p
-> from email e
-> group by e.date
-> order by e.date;
+------------+-------+
| date | p |
+------------+-------+
| 2020-01-11 | 0.333 |
| 2020-01-12 | 0.000 |
+------------+-------+
2 rows in set (0.00 sec)
147、分组查询(1)
该题目使用的表和数据如下:
/* 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,2,2,'2020-10-13'), (4,3,2,'2020-10-13'); */
数据表:login,表中数据如下:
mysql> select * from login;
+----+---------+-----------+------------+
| id | user_id | client_id | date |
+----+---------+-----------+------------+
| 1 | 2 | 1 | 2020-10-12 |
| 2 | 3 | 2 | 2020-10-12 |
| 3 | 2 | 2 | 2020-10-13 |
| 4 | 3 | 2 | 2020-10-13 |
+----+---------+-----------+------------+
4 rows in set (0.00 sec)
【问题】请编写 SQL 语句查询每个用户最近一天登录的日子,按照 user_id 升序排序,查询结果如下:
user_id | id |
---|---|
2 | 2020-10-13 |
3 | 2020-10-13 |
解答:
/* select user_id,max(date) id from login group by user_id order by user_id; */
mysql> select user_id,min(date) id
-> from login
-> group by user_id
-> order by user_id;
+---------+------------+
| user_id | id |
+---------+------------+
| 2 | 2020-10-12 |
| 3 | 2020-10-12 |
+---------+------------+
2 rows in set (0.00 sec)
148、分组查询(2)
该题目使用的表和数据如下:
/* 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'); */
登录记录表:login,表中数据如下:
mysql> select * from login;
+----+---------+-----------+------------+
| id | user_id | client_id | date |
+----+---------+-----------+------------+
| 1 | 2 | 1 | 2020-10-12 |
| 2 | 3 | 2 | 2020-10-12 |
| 3 | 2 | 2 | 2020-10-13 |
| 4 | 3 | 2 | 2020-10-13 |
+----+---------+-----------+------------+
4 rows in set (0.00 sec)
用户表:user,表中数据如下:
mysql> select * from user;
+----+----------+
| id | name |
+----+----------+
| 1 | tm |
| 2 | fh |
| 3 | wangchao |
+----+----------+
3 rows in set (0.00 sec)
客户端表:client,表中数据如下:
mysql> select * from client;
+----+--------+
| id | name |
+----+--------+
| 1 | pc |
| 2 | ios |
| 3 | anroid |
| 4 | h5 |
+----+--------+
4 rows in set (0.00 sec)
【问题】请编写一个 SQL 语句查询每个用户最近一天登录的日子,用户的名字,以及用户使用的设备的名字,查询结果按照 user 的 name 升序排序,查询结果如下:
u_n | c_n | date |
---|---|---|
fh | ios | 2020-10-13 |
wangchao | ios | 2020-10-13 |
解答:
/* select u_n, c.name c_n, a.date from (select u.id, u.name u_n, max(date) date from login l join user u on l.user_id = u.id group by u.id, u_n) a join login l on a.id = l.user_id and a.date = l.date join client c on l.client_id = c.id order by u_n; */
mysql> select u_n, c.name c_n, a.date
-> from (select u.id, u.name u_n, max(date) date
-> from login l join user u on l.user_id = u.id
-> group by u.id, u_n) a join login l on a.id = l.user_id and a.date = l.date
-> join client c on l.client_id = c.id
-> order by c_n;
+----------+-----+------------+
| u_n | c_n | date |
+----------+-----+------------+
| wangchao | ios | 2020-10-13 |
| fh | ios | 2020-10-13 |
+----------+-----+------------+
2 rows in set (0.04 sec)
149、自连接查询(1)
该题目使用的表和数据如下:
/* 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'); */
登录记录表:login,表中数据如下:
mysql> select * from 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 | 4 | 1 | 2020-10-13 |
| 6 | 1 | 2 | 2020-10-13 |
| 7 | 1 | 2 | 2020-10-14 |
+----+---------+-----------+------------+
7 rows in set (0.00 sec)
【问题】请统计新登录用户的次日成功的留存率,查询结果如下:
p |
---|
0.500 |
说明:
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 没登录了,为失败的留存。
解答:
/* select round((select count(*) from login a join (select user_id, min(date) first_login_date from login group by user_id) b on a.user_id = b.user_id and adddate(a.date, -1) = first_login_date) / (select count(distinct user_id) total_login from login),3) p; */
mysql> select round((select count(*)
-> from login a join
-> (select user_id, min(date) first_login_date from login group by user_id) b
-> on a.user_id = b.user_id and adddate(a.date, -1) = first_login_date) /
-> (select count(distinct user_id) total_login from login),3) p;
+-------+
| p |
+-------+
| 0.500 |
+-------+
1 row in set (0.03 sec)
150、自连接查询(2)
该题目使用的表和数据如下:
/* 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'); */
登录记录表:login,表中数据如下:
mysql> select * from 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 |
+----+---------+-----------+------------+
8 rows in set (0.00 sec)
【问题】请编写一个 SQL 语句,查询每个日期登录新用户个数,查询结果按照日期升序排序,查询结果如下:
date | new |
---|---|
2020-10-12 | 3 |
2020-10-13 | 0 |
2020-10-14 | 1 |
2020-10-15 | 0 |
解答:
/* select date, count(b.user_id) new from login a left join (select user_id, min(date) first_login_date from login group by user_id) b on a.user_id = b.user_id and a.date = b.first_login_date group by date order by date; */
mysql> select date, count(b.user_id) new
-> from login a left join
-> (select user_id, min(date) first_login_date from login group by user_id) b
-> on a.user_id = b.user_id and a.date = b.first_login_date
-> group by date
-> order by date;
+------------+-----+
| date | new |
+------------+-----+
| 2020-10-12 | 3 |
| 2020-10-13 | 0 |
| 2020-10-14 | 1 |
| 2020-10-15 | 0 |
+------------+-----+
4 rows in set (0.02 sec)
边栏推荐
猜你喜欢
随机推荐
RICON:NER SOTA 又来!
JUC(三):锁核心类AQS ing
FR9811S6 SOT-23-6 23V, 2A Synchronous Step-Down DC/DC Converter
"Digital Economy Panorama White Paper" Financial Digital User Chapter released!
日常开发写代码原则
基于英雄联盟的知识图谱问答系统
Redis发布订阅和数据类型
Go 语言快速入门指南: 介绍及安装
常用lambda表达式
SmobilerService 推送实现
Traceback (most recent call last): File
【倒计时5天】探索音画质量提升背后的秘密,千元大礼等你来拿
shell编程-测试
Android 技术面试准备(含面试题及答案)
PC client automation testing practice based on Sikuli GUI image recognition framework
SmobilerService 推送实现
浅谈SVN备份
bash case用法
Take you understand the principle of CDN technology
c语言进阶篇:内存函数