问题描述
有图书馆。每个图书馆都有很多书。每本书可能有多种状态(rent
、available
、unavailable
)。
我想获取 2020 年 rent
的所有图书。
所以我必须选择所有状态为 rent
且状态日期介于 2020-01-01
和 2021-01-01
之间的书籍以及(这就是最难的部分)具有最后状态之前的书籍2020-01-01 设置为 rent
。
我不知道如何实现。
图书馆:
id | 姓名 |
---|---|
1 | 我们没有书 |
2 | 我们有书 |
图书表:
状态表:
id | book_id | 状态 | 日期 |
---|---|---|---|
1 | 3 | 可用 | 2019-01-20 |
2 | 3 | 租金 | 2019-11-21 |
3 | 3 | 可用 | 2019-11-29 |
4 | 4 | 可用 | 2019-12-01 |
5 | 4 | 租金 | 2019-12-10 |
6 | 2 | 可用 | 2019-12-20 |
7 | 2 | 租金 | 2019-12-30 |
8 | 4 | 可用 | 2020-01-02 |
9 | 1 | 可用 | 2020-01-20 |
10 | 1 | 租金 | 2020-01-22 |
11 | 1 | 可用 | 2020-01-24 |
12 | 2 | 可用 | 2021-01-04 |
13 | 3 | 租金 | 2021-01-23 |
因此,我需要的查询应该返回 2020 年任何时候租借的所有书籍的所有书籍名称和图书馆名称。
所以预期的结果应该是这样的:
id | 图书馆 | 书 |
---|---|---|
1 | 我们没有书 | 标题 |
2 | 关于书籍的书 | 我们有书 |
3 | 维基百科印刷版 | 我们有书 |
- 预订
1
,因为在 2020 年设置了rent
状态 - 预订
2
,因为 2019 年是rent
,并于 2021 年返回(2020 年租金也是如此) - 预订
4
,因为它在 2019 年的最后一次状态是rent
图书 3
不包括在内,因为它在 2019 年的最后状态设置为 available
,并在 2021 年出租
解决方法
仅基于状态的简化答案涉及使用 max 函数和 2020 年的联合捕获 2019 年的最后状态
drop table if exists t;
create table t (id int auto_increment primary key,bid int,status varchar(20),dt date);
insert t(bid,status,dt) values
(3,'available','2019-01-20'),(3,'rent','2019-11-21'),'2019-11-29'),(4,'2019-12-01'),'2019-12-10'),(2,'2019-12-20'),'2019-12-30'),'2020-01-02'),(1,'2020-01-20'),'2020-01-22'),'2020-01-24'),'2021-01-04'),'2021-01-23');
select * from
(
select t.bid,t.status
from t
where (t.status = 'rent' and dt between '2020-01-01' and '2020-12-31')
limit 1
) a
union all
select t.bid,t.status
from t
join (select bid,max(id) id from t where dt < '2020-01-01' group by bid) s
on s.bid = t.bid and t.id = s.id
having status = 'rent'
;
+------+--------+
| bid | status |
+------+--------+
| 1 | rent |
| 4 | rent |
| 2 | rent |
+------+--------+
3 rows in set (0.022 sec)