第1关 查找购买个数超过20,重量小于50的商品,按照商品id升序排序
任务描述
如下有一张商品表(goods
),字段依次为:商品id
、商品名、商品质量
+------+------+--------+
| id | name | weight |
+------+------+--------+
| 1 | A1 | 100 |
| 2 | A2 | 20 |
| 3 | B3 | 29 |
| 4 | T1 | 60 |
| 5 | G2 | 33 |
| 6 | C0 | 55 |
+------+------+--------+
还有一张交易表(
trans
),字段依次为:交易id
、商品id
、这个商品购买个数
+------+----------+-------+
|tran_id| id | count |
+------+----------+-------+
| 1 | 3 | 10 |
| 2 | 1 | 44 |
| 3 | 6 | 9 |
| 4 | 1 | 2 |
| 5 | 2 | 65 |
| 6 | 5 | 23 |
| 7 | 3 | 20 |
| 8 | 2 | 16 |
| 9 | 4 | 5 |
| 10 | 1 | 3 |
+------+----------+-------+
查找购买个数超过
20
,重量小于50
的商品,按照商品id
升序排序,如:
+------+-------+
| id | total |
+------+-------+
| 2 | 81 |
| 3 | 30 |
| 5 | 23 |
+------+-------+
示例1
输入:
CREATE TABLE goods (
id int(11) NOT NULL,
name varchar(10) DEFAULT NULL,
weight int(11) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE trans (
tran_id int(11) NOT NULL,
id int(11) NOT NULL,
count int(11) NOT NULL,
PRIMARY KEY (tran_id)
);
insert into goods values(1,'A1',100);
insert into goods values(2,'A2',20);
insert into goods values(3,'B3',29);
insert into goods values(4,'T1',60);
insert into goods values(5,'G2',33);
insert into goods values(6,'C0',55);
insert into trans values(1,3,10);
insert into trans values(2,1,44);
insert into trans values(3,6,9);
insert into trans values(4,1,2);
insert into trans values(5,2,65);
insert into trans values(6,5,23);
insert into trans values(7,3,20);
insert into trans values(8,2,16);
insert into trans values(9,4,5);
insert into trans values(10,1,3);
输出:
id total
2 81
3 30
5 23
SELECT goods.id,sum(count) as total
FROM goods JOIN trans
WHERE goods.id=trans.id
AND weight<50
GROUP BY goods.id
HAVING total>20
ORDER BY goods.id
第2关 查询向follow表中user_id = 1 的用户,推荐其关注的人喜欢的音乐
任务描述
假设音乐数据库里面现在有几张如下简化的数据表:
关注follow
表,第一列是关注人的id
,第二列是被关注人的id
,这2
列的id
组成主键
+---------+-------------+
| user_id | follower_id |
+---------+-------------+
| 1 | 2 |
| 1 | 4 |
| 2 | 3 |
+---------+-------------+
这张表的第一行代表着用户
id
为1
的关注着id
为2
的用户
这张表的第二行代表着用户id
为1
的关注着id
为4
的用户
这张表的第三行代表着用户id
为2
的关注着id
为3
的用户个人的喜欢的音乐
music_likes
表,第一列是用户id
,第二列是喜欢的音乐id
,这2
列的id
组成主键
+---------+----------+
| user_id | music_id |
+---------+----------+
| 1 | 17 |
| 2 | 18 |
| 2 | 19 |
| 3 | 20 |
| 4 | 17 |
+---------+----------+
这张表的第一行代表着用户
id
为1
的喜欢music_id
为17
的音乐 …
这张表的第五行代表着用户id
为4
的喜欢music_id
为17
的音乐音乐
music
表,第一列是音乐id
,第二列是音乐name
,id
是主键
+----+------------+
| id | music_name |
+----+------------+
| 17 | yueyawang |
| 18 | kong |
| 19 | MOM |
| 20 | Sold Out |
+----+------------+
请你编写一个
MYSQL
,查询向user_id = 1
的用户,推荐其关注的人喜欢的音乐。不要推荐该用户已经喜欢的音乐,并且按music
的music_name
升序排列。你返回的结果中不应当包含重复项上面的查询结果如下:
+------------+
| music_name |
+------------+
| kong |
| MOM |
+------------+
示例1
输入:
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');
输出:
music_name
kong
MOM
select distinct music_name
from follow f
right join music_likes ml
on f.follower_id=ml.user_id
right join music m
on ml.music_id=m.id
where f.user_id=1
AND music_name not in(
select music_name
from music_likes mls
right join music m1
on mls.music_id=m.id
where mls.user_id=1
)
order by music_name;
第3关 查询向follow表中user_id用户,推荐其关注的人喜欢的音乐
任务描述
假设音乐数据库里面现在有几张如下简化的数据表:
关注follow
表,第一列是关注人的id
,第二列是被关注人的id
,这2列的id
组成主键
+---------+-------------+
| user_id | follower_id |
+---------+-------------+
| 1 | 2 |
| 1 | 4 |
| 2 | 3 |
+---------+-------------+
这张表的第一行代表着用户
id
为1
的关注着id
为2
的用户
这张表的第二行代表着用户id
为1
的关注着id
为4
的用户
这张表的第三行代表着用户id
为2
的关注着id
为3
的用户个人的喜欢的音乐
music_likes
表,第一列是用户id
,第二列是喜欢的音乐id
,这2
列的id
组成主键
+---------+----------+
| user_id | music_id |
+---------+----------+
| 1 | 17 |
| 2 | 18 |
| 2 | 19 |
| 3 | 20 |
| 4 | 17 |
+---------+----------+
这张表的第一行代表着用户
id
为1
的喜欢music_id
为17
的音乐 …
这张表的第五行代表着用户id
为4
的喜欢music_id
为17
的音乐
音乐music
表,第一列是音乐id
,第二列是音乐name
,id
是主键
+----+------------+
| id | music_name |
+----+------------+
| 17 | yueyawang |
| 18 | kong |
| 19 | MOM |
| 20 | Sold Out |
+----+------------+
请你编写一个
MYSQL
,查询向follow
表中user_id
用户,推荐其关注的人喜欢的音乐。不要推荐该用户已经喜欢的音乐,并且先按follow
的user_id
升序排列,再按music
的music_name
升序排列。你返回的结果中不应当包含重复项上面的查询结果如下:
+------------+
| music_name |
+------------+
| kong |
| MOM |
+------------+
示例1
输入:
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');
输出:
user_id music_name
1 kong
1 MOM
2 Sold Out
SELECT DISTINCT follow.user_id,music_name
FROM follow ,music_likes,music
WHERE follow.follower_id=music_likes.user_id
AND music.id=music_likes.music_id
AND music_id NOT IN(
SELECT music_id
FROM music_likes m
WHERE m.user_id=follow.user_id
)
ORDER BY user_id,music_name;
第4关 查询用户日活数及支付金额
任务描述
现有3张业务表,详见如下:
需要输出结果如下,没有支付的日期不需要显示,请写出对应的MYSQL
示例1
输入:
CREATE TABLE new_user(
user_id int(11) NOT NULL,
is_new int(11) NOT NULL,
PRIMARY KEY (user_id)
);
CREATE TABLE user_pay(
user_id int(11) NOT NULL,
pay_money int(11) NOT NULL,
dt char(20) NOT NULL
);
CREATE TABLE login_record(
user_id int(11) NOT NULL,
login_time char(20) NOT NULL,
dt char(20) NOT NULL
);
insert into new_user values(1,0);
insert into new_user values(2,1);
insert into new_user values(3,1);
insert into new_user values(4,0);
insert into new_user values(5,0);
insert into new_user values(6,1);
insert into new_user values(7,0);
insert into new_user values(8,1);
insert into user_pay values(1,30,'2021-11-10');
insert into user_pay values(1,100,'2021-11-10');
insert into user_pay values(2,500,'2021-11-11');
insert into user_pay values(2,200,'2021-11-12');
insert into user_pay values(3,1000,'2021-11-10');
insert into user_pay values(4,800,'2021-11-12');
insert into user_pay values(6,1200,'2021-11-10');
insert into user_pay values(6,700,'2021-11-14');
insert into login_record values(1,'8:00','2021-11-10');
insert into login_record values(1,'12:00','2021-11-10');
insert into login_record values(1,'13:00','2021-11-10');
insert into login_record values(2,'16:00','2021-11-10');
insert into login_record values(2,'12:35','2021-11-11');
insert into login_record values(2,'18:34','2021-11-12');
insert into login_record values(3,'20:00','2021-11-10');
insert into login_record values(4,'21:00','2021-11-12');
insert into login_record values(5,'21:00','2021-11-13');
insert into login_record values(6,'22:30','2021-11-10');
insert into login_record values(6,'13:30','2021-11-14');
输出:
dt dau dau_new total_pay total_pay_new
2021-11-10 4 3 2330 2200
2021-11-11 1 1 500 500
2021-11-12 2 1 1000 200
2021-11-14 1 1 700 700
SELECT ftemp1.dt AS dt,dau,dau_new,total_pay,total_pay_new
FROM(SELECT temp1.dt,dau,dau_new
FROM(SELECT tempt2.dt,COUNT(is_new) AS dau_new
FROM (SELECT DISTINCT user_id,dt FROM login_record)
AS tempt2,new_user
WHERE new_user.user_id=tempt2.user_id
GROUP BY tempt2.dt,is_new
HAVING is_new=1) AS temp1,(SELECT tempt2.dt,COUNT(is_new) AS dau
FROM (SELECT DISTINCT user_id,dt FROM login_record) AS tempt2,new_user
WHERE new_user.user_id=tempt2.user_id
GROUP BY tempt2.dt)AS temp2
WHERE temp1.dt=temp2.dt) AS ftemp1,(SELECT temp3.dt,total_pay,total_pay_new
FROM (SELECT dt,SUM(pay_money) AS total_pay
FROM user_pay
GROUP BY dt)AS temp3,(SELECT user_pay.dt,SUM(pay_money) AS total_pay_new
FROM user_pay,new_user
WHERE user_pay.user_id=new_user.user_id
GROUP BY dt,is_new
HAVING is_new=1) AS temp4
WHERE temp3.dt=temp4.dt) AS ftemp2 WHERE ftemp1.dt=ftemp2.dt
第5关 查询某网站每个日期新用户的次日留存率
任务描述
本关任务:查询某网站每个日期新用户的次日留存率。相关知识
某网站每天有很多人登录,请你统计一下该网站每个日期新用户的次日留存率。
有一个登录(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
;注意:
1、本题的新用户不是真正的新用户定义,是本题给出的新用户定义;
2、MYSQL
里计算日期t2
与日期t1
差的函数为:datediff(t2,t1)
;
3、MYSQL
对某字段total
四舍五入保留3
位的函数为:round(total,3)
;
4、MYSQL
对把某字段total
为空的值置为0
的函数为:ifnull(total,0)
。示例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,1,2,'2020-10-13'),
(6,3,1,'2020-10-14'),
(7,4,1,'2020-10-14'),
(8,4,1,'2020-10-15');
输出:
date p
2020-10-12 0.667
2020-10-13 0.000
2020-10-14 1.000
2020-10-15 0.000
SELECT first1.date,ROUND (COUNT(second2.user_id)/COUNT(first1.user_id),3)AS p
FROM(
SELECT user_id, MIN(date) AS date
FROM login
GROUP BY user_id)first1
LEFT JOIN login second2 ON first1.user_id=second2.user_id
AND second2.date=date_add(first1.date,INTERVAL+1 DAY)
GROUP BY first1.date
UNION
SELECT date,0 AS p
FROM login
WHERE date NOT IN(
SELECT MIN(date)
FROM login
GROUP BY user_id)
ORDER BY date;
第6关 查询满足条件的用户
任务描述
有的同学会购买网上训练课程来学习,某教育网站对购买记录会产生订单存到数据库,有一个订单信息表(order_info
),表内容如下:第
1
行表示user_id
为557336
的用户在2021-10-10
的时候使用了client_id
为1的客户端下了C++
课程的订单,但是状态为没有购买成功。第2
行为购买成功。查询满足以下条件的用户:
在2021-10-15
以后,如果有一个用户下单2
个以及2
个以上状态为购买成功的C++
课程或Java
课程或Python
课程,那么输出这个用户的user_id
,以及满足该条件的第一次购买成功的日期first_buy_date
,以及满足前面条件的第二次购买成功的日期second_buy_date
,以及购买成功的次数cnt
,并且输出结果按照user_id
升序排序。函数提示
1、row_number() over(partition by某字段 order by 某字段)
:窗口函数按某字段分组,生成从1
开始的顺序编号。
2、count(*) over(partition by 某字段)
:求分组后的总数。示例1
输入:
drop table if exists order_info;
CREATE TABLE order_info(
id int(4) NOT NULL,
user_id int(4) NOT NULL,
product_name char(20) NOT NULL,
status char(20) 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,'2021-10-10'),
(2,230173543,'Python','completed',2,'2021-10-12'),
(3,230173543,'Python','completed',2,'2021-10-15'),
(4,557336,'Java','completed',1,'2021-10-15'),
(5,230173543,'Java','no_completed',2,'2021-10-16'),
(6,230173543,'Java','completed',2,'2021-10-20'),
(7,230173543,'C++','completed',2,'2021-10-21'),
(8,557336,'Java','completed',1,'2021-10-21'),
(9,557336,'离散数学','completed',1,'2021-10-22'),
(10,230173543,'离散数学','completed',2,'2021-10-22'),
(11,663466,'离散数学','completed',3,'2021-10-22'),
(12,663466,'C++','completed',3,'2021-10-22'),
(13,663466,'Python','no_completed',3,'2021-10-23'),
(14,663466,'Python','completed',3,'2021-10-24'),
(15,663466,'C++','completed',3,'2021-10-25'),
(16,8912311,'Java','completed',1,'2021-10-25'),
(17,3345600,'高等数学','completed',1,'2021-10-27'),
(18,3345600,'数学分析','completed',1,'2021-10-28'),
(19,3345600,'数据库系统','completed',1,'2021-10-28');
输出:
user_id first_buy_date second_buy_date cnt
663466 2021-10-22 2021-10-24 3
230173543 2021-10-20 2021-10-21 2
SELECT user_id,
MIN(CASE WHEN num=1 THEN date END) AS first_buy_date,
MAX(CASE WHEN num=2 THEN date END) AS second_buy_date,
COUNT(1) AS cnt
FROM(
SELECT*,row_number()over(PARTITION BY user_id ORDER BY date) AS num
FROM order_info
WHERE status='completed'
AND date >'2021-10-15'
AND product_name IN('C++','Java','Python'))TABLE2
GROUP BY user_id
HAVING COUNT(1)>=2;
第7关 查询各工程号最大的按零件号合计供应量以及该零件号,并先按工程号升序,再按零件号升序排序。
任务描述
查询各工程号最大的按零件号合计供应量以及该零件号,并先按工程号升序,再按零件号升序排序。相关知识
供应情况表SPJ
由供应商代码(SNO
)、零件代码(PNO
)、工程项目代码(JNO
)、供应数量(QTY
)组成,标识某供应商
供应某种零件 给某工程项目的数量为QTY
。
SPJ
表如下图:现已构建
SPJ
表,结构信息如下:
CREATE VIEW nextdata(JNO,PNO,maxsum)
AS
SELECT JNO,PNO,SUM(QTY)
FROM SPJ
GROUP BY JNO,PNO
ORDER BY JNO,PNO;
SELECT JNO,PNO,maxsum
FROM nextdata AS S1
WHERE S1.maxsum >= ALL(
SELECT maxsum
FROM nextdata AS S2
WHERE S1.JNO = S2.JNO);