选择与日期边界和这些日期之前的最后一本“租借”书相匹配的行

问题描述

有图书馆。每个图书馆都有很多书。每本书可能有多种状态(rentavailableunavailable)。

我想获取 2020 年 rent 的所有图书。

所以我必须选择所有状态为 rent 且状态日期介于 2020-01-012021-01-01间的书籍以及(这就是最难的部分)具有最后状态之前的书籍2020-01-01 设置为 rent

我不知道如何实现。


图书馆:

id 姓名
1 我们没有书
2 我们有书

图书表:

id library_id 标题
1 1 标题
2 2 关于书籍的书
3 1 堆栈溢出。您不关心的最佳问题。
4 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)