Как подсчитать количество забронированных ночей в месяц с датами заезда и выезда, имеющими разные месяцы в SQL?

#mysql #sql

Вопрос:

У меня есть набор данных, подобный приведенному ниже набору данных. Я хочу найти количество ночей, которые каждый идентификатор был занят в месяц. Для некоторых строк даты заезда и выезда указаны в разные месяцы. Я хочу знать, как написать запрос, чтобы получить заполняемость в месяц. Например, для id = 1, регистрация заезда: 2020-01-26 и дата выезда: 2020-03-02. Как я могу получить таблицу, которая показывает заполняемость января: 6, заполняемость февраля: 29 и заполняемость марта: 1

ID регистрация заезда Оформить покупку
1 2020-01-26 2020-03-02
2 2020-04-01 2020-04-20
3 2020-06-29 2020-07-03

Результат должен быть таким:

ID Месяц Заполняемость
1 Янв. 06
1 Февраль 29
1 Март 01
2 Апрель 19
3 Июнь 02
3 Июль 02

Комментарии:

1. Покажите, что вы пробовали до сих пор….

Ответ №1:

во-первых, вам нужен numbers table или tally table , после того, как вы можете легко получить его с помощью этого запроса :

 select c.id,
    case when m.id <> 0 
        then adddate(last_day(adddate(checkin_date, interval m.id -1 month)),interval 1 day)
        else checkin_date 
    end as Checkin_date,
    case when last_day(adddate(checkin_date, interval m.id month)) > checkout_date 
        then checkout_date 
        else last_day(adddate(checkin_date, interval m.id month)) 
    end checout_date,
    datediff(case when last_day(adddate(checkin_date, interval m.id month)) > checkout_date 
                then checkout_date 
                else last_day(adddate(checkin_date, interval m.id month)) end,
             case when m.id <> 0 
                then last_day(adddate(checkin_date, interval m.id -1 month))
                else adddate(checkin_date, interval -1 day) end
            ) daysdiff
from checkins c
join numbers m on m.id <= period_diff(date_format(checkout_date, "%Y%m"),date_format(checkin_date, "%Y%m"))
order by  c.id, checkin_date
 

это работает для любого промежутка (более 1 года)

вы можете использовать date_format для отображения месяца :

 select
     date_format(case when m.id <> 0 
        then adddate(last_day(adddate(checkin_date, interval m.id -1 month)),interval 1 day)
        else checkin_date 
    end, '%Y %M') as month_year
    ,sum(datediff(case when last_day(adddate(checkin_date, interval m.id month)) > checkout_date 
                then checkout_date 
                else last_day(adddate(checkin_date, interval m.id month)) end,
             case when m.id <> 0 
                then last_day(adddate(checkin_date, interval m.id -1 month))
                else adddate(checkin_date, interval -1 day) end
            )) Occupancy
from checkins c
join numbers m on m.id <= period_diff(date_format(checkout_date, "%Y%m"),date_format(checkin_date, "%Y%m"))
group by date_format(case when m.id <> 0 
        then adddate(last_day(adddate(checkin_date, interval m.id -1 month)),interval 1 day)
        else checkin_date 
    end, '%Y %M') 
order by month_year
 
  month_year    | Occupancy
 :------------ | --------:
 2020 April    |        20
 2020 February |        29
 2020 January  |         6
 2020 July     |         3
 2020 June     |         2
 2020 March    |         2
 

db<>скрипка здесь

Комментарии:

1. Я не знал о Fiddle (онлайн-интерфейс БД). Новое обучение 🙂 @eshirvana Спасибо, что поделились

2. Спасибо за вашу помощь. Я отредактировал свой вопрос, чтобы показать, какого результата я хочу достичь

3. @Rahom смотрите Обновленный ответ

Ответ №2:

Если я правильно понимаю, вам нужен агрегированный результат по месяцам занятого инвентаря.

Вы можете попробовать ниже простой агрегированный запрос, основанный на предложении ‘Group by’, а затем добавить дополнительную логику критериев, основанную на ваших потребностях, если требуется

 select monthname(check_in) as 'Month', sum(dayofyear(check_out) - dayofyear(check_in)) as 'Occupied_days'
from inventory 
where year(check_in)=year(check_out) 
group by 1;
 

Примечание: Приведенный выше запрос будет работать только для набора данных, где check_in и check_out произошли в течение того же года.

Проверьте пример вывода запроса здесь, в Fiddle

Комментарии:

1. Этот запрос совместим с mysql для другой базы данных, вы можете попробовать аналогичные функции БД.

2. Спасибо за вашу помощь. Я отредактировал свой вопрос, чтобы показать, какого результата я хочу достичь