【发布时间】:2021-06-25 21:04:02
【问题描述】:
我拥有经常出租的东西。它由几个部分组成。它可以部分租用,也可以整体租用。如果一个部分被出租,您将无法将它作为一个整体出租。
例如,我租了一辆车。这辆车有轮胎,也是出租的。您可以选择租用轮胎(«整体»)的汽车,或者只租一个轮胎。但是,如果租用一个或多个轮胎,您将无法租用汽车(“整车”)。
我把它想象成一个层次结构。
Whole
_______|_______
| |
Part 1 Part 2
我使用一个 Google 日历来处理“整个”事情,并为每个包含部分使用单独的日历。这行得通,但是很烦人,我希望能够将链接发送给感兴趣的人-他们可以在其中查看可用的内容。
所以我创建了一个非常简单的数据库(mariadb 10.4),有两个表:
# tbl: part
| id | parent_id | name |
parent_id 列仅引用同一张表中的另一行,这是数据示例。
| 1 | NULL | Car |
| 2 | 1 | Tire 1 |
| 3 | 1 | Tire 2 |
那么下面的表格来存储每个部分是booked时的日期(+示例数据)。
# tbl: booking
| id | part_id | booked_from | booked_until |
--------------------------------------------
| 1 | 1 | 2021-07-31 | 2021-08-03 |
| 2 | 2 | 2021-08-03 | 2021-08-07 |
| 3 | 3 | 2021-08-04 | 2021-08-06 |
| 4 | 3 | 2021-08-09 | 2021-08-10 |
据此我们知道汽车本身是从2021-07-31 - 2021-08-03 预订的,但它只能从2021-08-06 预订,因为在此期间有两个轮胎出租(但是它们可以在同时它们不是严格相关的)。但是直到2021-08-09,因为一个轮胎又被预订了。
我正在寻找的是一个查询以获取可用日期列表。从pars-table 我能够找出哪些部分是相关的,这不是我最大的问题 - 我想,因为在查询可用性时可以使用这样的东西:
- 汽车:
part_id IN(1,2,3) - 轮胎 1:
part_id IN(1,2) - 轮胎 3:
part_id IN(1,3)
我的问题是(很简单?)我如何编排一个只返回可用日期的查询,尤其是对于日期可以重叠的汽车。
例如汽车的结果
SELECT
`booked_until` AS `available-from`,
`booked_from` as `available-until`
FROM
booking
/** some JOIN magic? **
WHERE part_id IN(1,2,3)
例如 tire 1 将是相同的,但 part_id IN(1,2) 因为 tire 2 (id: 3) 与 tire 1 没有直接关系。
两者都应该分别返回:
# car
| available-from | available-until |
------------------------------------
| NULL | 2021-07-31 |
| 2021-08-06 | 2021-08-09 |
| 2021-08-10 | NULL |
# tire 1
| available-from | available-until |
------------------------------------
| NULL | 2021-07-31 |
| 2021-08-07 | NULL |
NULL-values 只是表示之前或之前没有任何预订。例如,此轮胎在from now 之前可用,直到2021-07-31 和从2021-08-07 到地球存在的最后一天。
希望这是有道理的 - 并且有人能够提供帮助。
提前谢谢你。
【问题讨论】:
-
你用的是mysql 8吗?否则这种树的功能有限
-
嗨,我正在使用 MariaDB
mysql Ver 15.1 Distrib 10.4.18-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2 -
然后看看递归 ctes
-
谢谢。看过了,但无论我怎样称呼
WITH语句(例如cte_availability),它都会以#1146 - Table '<db>.cte_availability' doesn't exists失败。 -
我在下面添加了一个没有递归 ctes 的解决方案。
标签: mysql sql database gaps-and-islands mariadb-10.4