postgresql 如何检查未使用范围内的日期?

x6492ojm  于 2023-03-17  发布在  PostgreSQL
关注(0)|答案(3)|浏览(173)

我写了一个租赁软件,但我没有得到任何进一步...
我有这样一张table:

car_id
date_from
date_to

当任何人想租这个日期:

DATE_FROM: 2023-09-09
DATE_TO: 2023-09-15

现在我必须检查数据库中所有未使用的日期。

SELECT 

car_id,
date_from,
date_to

FROM cars

INNER JOIN (
 SELECT date_from, date_to FROM booking WHERE (DATE_FROM NOT between date_from AND date_to) AND (DATE_TO NOT BETWEEN date_from AND date_to 
)

idk我做错了什么,我希望任何人都能帮助我解决这个问题
非常感谢!!

yyyllmsg

yyyllmsg1#

在PostgreSQL中,您可以为预订间隔部署datarange data type
该表将具有以下DDL

create table booking 
(car_id int,
 booking_range daterange
)

你的样本参数范围是'[2023-09-09, 2023-09-15]'::daterange
注意,* 方括号 * 表示两端都是 * 包括 *,括号)是 * 不包括 *。
使用以下示例数据

insert into booking(car_id, booking_range)
values
(2, '[2022-10-01, 2022-10-10]'::daterange),
(2, '[2023-10-01, 2023-10-10]'::daterange),
(3, '[2023-09-10, 2023-09-20]'::daterange),
(4, '[2023-09-11, 2023-09-12]'::daterange),
(5, '[2023-08-10, 2023-09-10]'::daterange)

您可以使用 overlap 运算符&&来标识 * 与您的范围重叠 * 的预订。

select * from booking 
where '[2023-09-09, 2023-09-15]'::daterange && booking_range
;

car_id|booking_range          |
------+-----------------------+
     3|[2023-09-10,2023-09-21)|
     4|[2023-09-11,2023-09-13)|
     5|[2023-08-10,2023-09-11)|

您要执行的查询是获取与参数范围 * 重叠的所有未预订汽车 * -将简单的not in与上述子查询结合使用:

select * from car
where car_id not in 
(
  select car_id from booking 
  where '[2023-09-09, 2023-09-15]'::daterange && booking_range
)
l5tcr1uw

l5tcr1uw2#

诀窍在于当(s1〈e2)和(s2〈e1)时,两个区间(s1,e1)和(s2,e2)重叠。
下面的选择为您提供给定间隔内的所有可用车厢(在示例01/07/2023-01/27/2023

select id as car_id,
'01/07/2023' as date_from,
'01/27/2023' as date_to
from car c
where c.id not in (
    select car_id
    from booking
    where date_from < '01/27/2023'
    and date_to > '01/07/2023'
)

对于此架构,测试数据

create table car (
   id integer
);

create table booking(
    car_id integer,
    date_from timestamp, 
    date_to timestamp
);

insert into car values
(1),
(2),
(3),
(4),
(5),
(6)
;

insert into booking values
    (1, '01/01/2023', '01/10/2023'),
    (1, '01/20/2023', '01/30/2023'),
    (2, '01/05/2023', '01/08/2023'),
    (3, '01/23/2023', '01/29/2023'),
    (4, '01/15/2023', '01/16/2023'),
    (5, '01/01/2023', '01/03/2023'),
    (5, '01/28/2023', '01/30/2023')
;

结果是
| 汽车标识|日期_从|日期_至|
| - ------|- ------|- ------|
| 五个|2023年7月1日|2023年1月27日|
| 六个|2023年7月1日|2023年1月27日|
Play with it on DB-Fiddle
根据< and >您的具体要求,您可能需要用〈=和〉=替换。

gk7wooem

gk7wooem3#

据我所知,问题陈述是基于某个日期的可用性作为输入参数。所以这个查询将工作。

DECLARE @cars TABLE (car_id int);
DECLARE @Booking TABLE (car_id int, date_from DATE,date_to DATE);

INSERT INTO @cars(car_id)
VALUES('2'),('1');

INSERT INTO @Booking
(
car_id,
date_from,
date_to
)
VALUES
(   1, '2023-01-11',  '2023-01-15'),
(   1, '2023-01-05',  '2023-01-08'),
(   2, '2023-01-12',  '2023-01-14')

-- Now if you want to check the availiblity from 12th Jan to 13th Jan
DECLARE @DATE_FROM DATE = '2023-01-12'
DECLARE @DATE_TO DATE = '2023-01-13'

SELECT 
C.car_id,
@DATE_FROM AS date_to,
@DATE_TO AS date_to
FROM @cars C
LEFT JOIN @booking B ON C.car_id = B.car_id
WHERE @DATE_FROM NOT between date_from AND date_to AND @DATE_TO NOT 
BETWEEN date_from AND date_to OR B.car_id IS NULL

相关问题