Tino Fourie Ответов: 2

Как рассчитать разницу во времени между двумя непересекающимися записями с помощью mysql


Я использую планировщик (календарь) в приложении WinForms (vb.net) и сохранять встречи (startDateTime &endDateTime) в базе данных MySql.

В процессе записи на прием мне нужно проверить, доступен ли определенный ресурс (например, комната) в течение определенного периода времени (минут) в определенный день.

Я искал здесь возможные решения, соответствующие моему сценарию, однако все решения относятся к поиску записей в течение определенного периода времени.

Я сохраняю время начала и окончания встречи в БД, а также все необходимые ресурсы для этой встречи.

Я могу иметь несколько ресурсов (например, более одной комнаты) и хотел бы иметь возможность найти комнату с не выделенным периодом времени, если ресурсы по умолчанию (или выбранные комнаты) не будут доступны в течение этого периода времени.

Период времени может варьироваться от 10 минут до 2 часов, но это всегда будет установленный период для типа назначения и ресурса, например: назначение: заседание Совета директоров

Ресурс: Зал Заседаний Совета Директоров

Время Начала: 02/02/2019 09:00:00

Время Окончания: 02/02/2019 10:00:00

Любая помощь будет оценена по достоинству.

Что я уже пробовал:

Код, с которым я играю:

SELECT (TIME(b.appStartTime) - TIME(a.appEndTime)) as timedifference, 
a.appID, a.appOwnerKey, a.appEndTime, b.appStartTime, a.appSubject, 
a.appDescription, a.appToolTip, a.appCategory, a.appImg, a.appPatWaiting

FROM cusAppointments a 
INNER JOIN cusAppointments b ON b.appID = (a.appID + 1)
WHERE (DATE(a.appStartTime) = DATE(NOW()) AND
       DATE(b.appEndTime) = DATE(NOW()))
AND (TIME(b.appStartTime) - TIME(a.appEndTime)) >= 15000
AND a.appOwnerKey = 'Admin .'
ORDER BY a.appStartTime ASC;


Это не работает, потому что в моем сознании я должен работать с двумя наборами записей одной и той же таблицы, упорядоченными по StartTime, а затем вычесть EndTime rowid набора записей A из StartTime rowid набора записей B + 1.

Maciej Los

Можете ли вы предоставить "короткую версию" и небольшой фрагмент данных в следующем формате: appID, appStartTime, appEndTime и т. д.? Какое поле является первичным ключом?

Tino Fourie

Привет, Мацей, спасибо за ваш комментарий.

AppID-это PK, однако было бы бессмысленно даже рассматривать appID, потому что у меня могут быть последовательные appID, но не последовательные периоды времени.

appID = INT(11) автоматическое увеличение
appStartTime = DateTime (2019-01-01 10:00:00)
appEndTime = DateTime (2019-01-01 10:15:00)

Я действительно ищу времена, когда ресурсы не забронированы, однако пользователь не сможет увидеть, забронирован ли ресурс или нет, потому что тип бронирования будет определять, какой период времени будет между appStartTime и appEndTime.

Richard Deeming

Мне это кажется неправильным. Если я закажу 2-часовую встречу с 3 вечера сегодня, а номер будет доступен только в течение 2 часов с 9 утра, то я не буду считать это приемлемой альтернативой.

Вы ищете ресурсы, которые не имеют перекрывающегося бронирования вместо этого?

Maciej Los

Похоже, ОП ищет пробелы и островки в дате и времени...

2 Ответов

Рейтинг:
10

Tino Fourie

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

Вещи, которые я не принял во внимание:
1. StartOfDay времени (начала рабочего дня)
2. Время окончания рабочего дня (конец рабочего дня)
3. получить первое бронирование - проверить наличие не выделенного периода времени между первым бронированием и стартовым днем
4. получить последнее бронирование - проверить наличие незапланированного периода времени между последним бронированием и окончанием рабочего дня

Я использовал простой блок операторов If..Else для реализации логики, и для проверки всего требуется всего 11 строк кода.
Сначала я проверяю наличие первого бронирования, а затем проверяю, есть ли у меня открытый период времени между временем начала первого бронирования и временем начала дня.

Вторая проверка предназначена для последнего бронирования, чтобы увидеть, есть ли отверстие между временем окончания последнего бронирования и временем окончания рабочего дня.

Третья часть-это обработка всех бронирований между первым и последним бронированием.

'(1) Check if there is a TimeSlot available between the first returned record and the Start Of Day
                    '   - Check if we have the first record (j=0)
                    '   - Check if myEndTime is less or equal to dbStartTime of first record
                    '   - Check if myStartTime is greater or equal to StartOfDay
                    '   - Check the Time Difference between dbStartTime of first record and StartOfDay and check if
                    '       myTimeSlot is less or equal to that time

                    If j = 0 AndAlso myEndTime <= dbStartTime AndAlso
                        myStartTime >= StartOfDay AndAlso (dbStartTime - StartOfDay) >= myTimeSlot Then
                        txtResults.AppendText("Found Time Slots" & vbCrLf)
                        'Check for LAST record and do similar as for FIRST record
                    ElseIf j = clReadFromDB.tmsData.Rows.Count - 1 AndAlso myEndTime <= EndOfDay AndAlso
                        (EndOfDay - dbEndTime) >= myTimeSlot Then
                        txtResults.AppendText("Found Time Slots" & vbCrLf)
                        'Check for a time slot inbetween the FIRST and LAST record
                        '   - We don't have to bother with checking for StartOfDay or EndOfDay
                        '   - Check if myStartTime >= dbEndTime of the Current Record (j)
                        '   - Check if myEndTime <= dbStartTime of the Next Record (j+1)
                        '   - Check if myTimeSlot is <= to the time difference between dbDStartTime of Current Record
                        '     and dbStartTime of the Next Record
                    ElseIf myStartTime >= clReadFromDB.tmsData.Rows(j).Item(2) AndAlso
                        myEndTime <= clReadFromDB.tmsData.Rows(j + 1).Item(1) AndAlso
                        (clReadFromDB.tmsData.Rows(j + 1).Item(1) - clReadFromDB.tmsData.Rows(j).Item(2)) >= myTimeSlot Then
                        txtResults.AppendText("Found Time Slots" & vbCrLf)
                        lblStatus.Text = Convert.ToString(clReadFromDB.tmsData.Rows(j + 1).Item(1) - clReadFromDB.tmsData.Rows(j).Item(2))
                    Else
                        lblStatus.Text = "Time Slot not found"
                        txtResults.AppendText("Time Slot Not Found" & vbCrLf)
                    End If


Я буду использовать приведенный выше код в качестве базовой логики, потому что он проходит через все заказы в БД. Он также использует первое бронирование в качестве первоначального чека вместо календарного времени, выбранного пользователем для нового бронирования.

Спасибо тем, кто пытался помочь, хотя ваши предложения и не приблизили меня к решению MySQL, однако они расширили мои знания о MySQL.


Рейтинг:
1

Maciej Los

Я не уверен, чего вы хотите достичь, потому что вы не отвечаете на комментарии, но кажется, что вы ищете алгоритм, который будет находить пробелы и острова. Пожалуйста, обратитесь к этому: mysql - определение пробелов и островов - администраторы баз данных Stack Exchange[^]


Tino Fourie

Мои извинения за поздний ответ - я сам ждал ответа 2 дня.

Мне посоветовали заглянуть в аналитические функции - LEAD и LAG, однако это было немного выше моей головы (и до сих пор есть) базовый пример кода, который я пробовал, вообще не работал, а MySQL Workbench не предоставляет четких отладочных сообщений.

Спасибо вам за это , я обязательно разберусь с этим.