计算连续预订的 SQL 查询

问题描述 投票:0回答:1

到目前为止,我提出了以下查询:

SELECT
    SUM(CASE WHEN CAST(check_in AS date) = CAST('$date' as date) THEN 1 ELSE 0 END) AS total_arrivals,
    SUM(CASE WHEN CAST(check_out AS date) = CAST('$date' as date) THEN 1 ELSE 0 END) AS total_departures,
    SUM(CASE WHEN (CAST(check_in AS date) <= CAST('$date' as date) AND CAST(check_out AS date) > CAST('$date' as date)) THEN 1 ELSE 0 END) AS total_stayovers
FROM bookings_beds24

上面非常简单的查询需要一个

$date
并计算该日期的
check_in
check_out
和停留时间。

我希望创建一个查询,使我能够计算/计算switchovers。转换是两个不同的预订,一个在同一天退房,另一个在同一天入住。

你认为仅使用 sql 查询就可以实现这样的事情吗?我目前正在迁移上述三个查询,同时我希望能够计算连续的预订。

请记住,bookings_beds24 表包含

check_in
check_out
日期和
room_id
因为它存储多个房间的数据。

编辑:目前正在做类似的事情,但显然行不通:

SELECT * 
FROM 
    (SELECT check_in FROM bookings_beds24 WHERE room_id='208979') AS a, 
    (SELECT COUNT(book_id) AS total FROM bookings_beds24 WHERE check_out=a.check_in AND room_id='208979') AS b;
mysql sql subquery aggregate-functions date-arithmetic
1个回答
0
投票

我将从部分改写您当前的查询开始。

假设:

  • check_in
    check_out
    datetime
    timestamp
    数据类型(意味着它们存储日期 时间)
  • $date
    是查询参数 (
    ?
    ),它以
    date
    (没有时间部分)的形式给出

我们可以:

  • 使用子查询,这样我们就不需要多次重复参数
  • 将部分日期过滤逻辑移至
    on
    join
  • 子句
  • 避免转换时间戳并使用半开间隔进行过滤(这样效率更高)
  • 利用 MySQL 在数字上下文中将谓词评估为
    0
    (假)和
    1
    (真)这一事实来缩短条件
    sum
    s.

所以:

select 
    sum(b.check_in  >= r.refdate)                  as total_arrivals,
    sum(b.check_out <  r.refdate + interval 1 day) as total_departures,
    sum(b.check_in < r.refdate and b.check_out >= r.refdate + interval 1 day) as total_stayovers
from (select ? refdate) r
inner join bookings_beds24 b 
    on b.check_in < r.refdate + interval 1 day and b.check_out >= r.refdate

我怀疑你对逗留的定义;您的查询将当天的所有到达和离开都计为停留,这似乎不正确;我的只考虑在参考日期之前开始并在之后的一天结束的预订。


在计算切换时:一种选择是按房间预先聚合,这样我们就可以识别发生在同一房间的到达/离开:

select 
    sum(arrivals)                        as total_arrivals, 
    sum(departures)                      as total_departures, 
    sum(stayovers)                       as total_stayovers,
    sum(arrivals = 1 and departures = 1) as total_switchovers
from (
    select b.room_id,
        sum(b.check_in  >= r.refdate)                  as arrivals,
        sum(b.check_out <  r.refdate + interval 1 day) as departures,
        sum(b.check_in < r.refdate and b.check_out >= r.refdate + interval 1 day) as stayovers
    from (select ? refdate) r
    inner join bookings_beds24 b 
        on b.check_in < r.refdate + interval 1 day and b.check_out >= r.refdate
    group by b.room_id
) b

请注意,在这种逻辑下,切换总是与出发和到达一样重要(另一方面,当然并非所有出发或到达都是切换)。


这是一些示例数据,我们将用作参考日期

'2023-04-07'
.

create table bookings_beds24 (
    room_id int,
    check_in datetime,
    check_out datetime
);
insert into bookings_beds24 values 
    (1, '2023-07-05 12:00:00', '2023-07-06 12:00:00'),  -- irrelevant
    (1, '2023-07-07 12:00:00', '2023-07-08 12:00:00'),  -- arrival
    (2, '2023-07-05 12:00:00', '2023-07-07 12:00:00'),  -- departure
    (3, '2023-07-05 12:00:00', '2023-07-08 12:00:00'),  -- stayover
    (4, '2023-07-06 12:00:00', '2023-07-07 12:00:00'),  -- switchover (departure)
    (4, '2023-07-07 12:00:00', '2023-07-10 12:00:00')   -- switchover (arrival)
;

运行日期查询

'2023-04-07'
收益率:

total_arrivals 总出发次数 total_stayovers total_switchovers
2 2 1 1

这里是一个DB小提琴

© www.soinside.com 2019 - 2024. All rights reserved.