Дата инкремента цикла хранимой процедуры MySQL в выбранном запросе возвращает последнюю дату - PullRequest
0 голосов
/ 22 февраля 2019

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

Хранимая процедура:

CREATE PROCEDURE `IBE_getAvailabilityForRange`(IN firstStayDate DATE, IN lastStayDate DATE)
BEGIN
DECLARE nextDate DATE;
SET nextDate = firstStayDate;
WHILE nextDate <= lastStayDate DO
SELECT nextDate as stayDate, Room_type, No_of_room, ArrivalDate, DepartDate, state FROM reservation_temp WHERE Reservation_is_done = 1 AND state != 0 AND ArrivalDate <= nextDate AND DepartDate > nextDate;
SET nextDate = DATE_ADD(nextDate, INTERVAL 1 DAY);
END WHILE;
END

Приведите ее к выводу при вызове call IBE_getAvailabilityForRange('2019-02-25', '2019-02-27');

stored procedure output

[РЕДАКТИРОВАТЬ] Мне нужно, чтобы вывести результаты за 2019-02-25, 2019-02-26, 2019-02-27.В настоящее время это дает мне результаты только для 2019-02-27.

[РЕДАКТИРОВАТЬ: отредактированная хранимая процедура с GROUP by и SUM]

BEGIN
DECLARE nextDate DATE;
SET nextDate = firstStayDate;
WHILE nextDate <= lastStayDate DO
SELECT nextDate as stayDate, Room_type, SUM(No_of_room), ArrivalDate, DepartDate, state FROM reservation_temp WHERE Reservation_is_done = 1 AND state != 0 AND ArrivalDate <= nextDate AND DepartDate > nextDate GROUP BY stayDate, Room_type;
SET nextDate = DATE_ADD(nextDate, INTERVAL 1 DAY);
END WHILE;

Ответы [ 3 ]

0 голосов
/ 22 февраля 2019

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

т.е.:

SELECT day1;
SELECT day2;

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

Однако вынужно лучше определить ваши GROUP BY столбцы для ArrivalDate, DepartDate и состояния.Поскольку в MySQL 5.7+ ONLY_FULL_GROUP_BY включен по умолчанию, произойдет ошибка.Я использовал MIN, MAX и добавил state к группировкам, чтобы избежать ошибок.

В качестве альтернативы явно используйте ANY_VALUE() для столбцов, чтобы разрешить MySQL выбирать значение в каждой группе, которое не было агрегировано. [sic]

CREATE PROCEDURE `IBE_getAvailabilityForRange`(IN firstStayDate DATE, IN lastStayDate DATE)
BEGIN
DECLARE nextDate DATE;

DROP TEMPORARY TABLE IF EXISTS tmp_stays;
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_stays(
    stayDate DATE,
    Room_type INT(10),
    rooms INT(10),
    ArrivalDate DATE,
    DepartDate DATE,
    state INT
);

SET nextDate = firstStayDate;
WHILE nextDate <= lastStayDate DO
    INSERT tmp_stays
    SELECT
       nextDate, 
       Room_type, 
       SUM(No_of_room), 
       MIN(ArrivalDate), 
       MAX(DepartDate), 
       state
    FROM reservation_temp 
    WHERE Reservation_is_done = 1 
    AND state != 0 
    AND ArrivalDate <= nextDate 
    AND DepartDate > nextDate 
    GROUP BY nextDate, Room_type, state;

    SET nextDate = DATE_ADD(nextDate, INTERVAL 1 DAY);
END WHILE;

SELECT * FROM tmp_stays;
DROP TEMPORARY TABLE IF EXISTS tmp_stays;
END

С набором данных (обратите внимание, что id 1 и 2 имеют разные значения DepartDate)

reservation_temp
---
| id | Room_type | state | No_of_room | ArrivalDate | DepartDate | Reservation_is_done | 
| ---: | ---: | ---: | ---: | --- | --- | ---: | 
| 1 | 1 | 1 | 1 | 2019-01-01 | 2019-01-02 | 1 | 
| 2 | 1 | 1 | 1 | 2019-01-01 | 2019-01-03 | 1 | 
| 3 | 1 | 1 | 1 | 2019-01-03 | 2019-01-04 | 1 | 
| 4 | 1 | 1 | 1 | 2019-01-04 | 2019-01-04 | 1 | 
| 5 | 1 | 1 | 1 | 2019-01-04 | 2019-01-05 | 1 | 

Результат

/* CALL IBE_getAvailabilityForRange('2019-01-01', '2019-01-05'); */

tmp_stays
---
| stayDate | Room_type | rooms | ArrivalDate | DepartDate | state | 
| --- | ---: | ---: | --- | --- | ---: | 
| 2019-01-01 | 1 | 2 | 2019-01-01 | 2019-01-03 | 1 | 
| 2019-01-02 | 1 | 1 | 2019-01-01 | 2019-01-03 | 1 | 
| 2019-01-03 | 1 | 1 | 2019-01-03 | 2019-01-04 | 1 | 
| 2019-01-04 | 1 | 1 | 2019-01-04 | 2019-01-05 | 1 | 
0 голосов
/ 22 февраля 2019

Вы можете посмотреть это обсуждение: создать дни из диапазона дат

Используя некоторые запросы из обсуждения, вы можете получить список дат из диапазона дат.Затем просто внутренне / слева присоедините ваши данные, и вы получите то, что хотите.

С моей реализацией (у меня есть вспомогательная таблица + представление, но это не обязательно), результирующий запрос будет выглядеть примерно так:

SELECT
      Dates.d
    , reservation_temp.*
FROM
    global.Dates
    INNER JOIN reservation_temp ON (
            Reservation_is_done = 1
        AND state != 0
        AND ArrivalDate <= Dates.d
        AND DepartDate > Dates.d
    )
WHERE
    Dates.d BETWEEN firstStayDate AND lastStayDate
0 голосов
/ 22 февраля 2019

Я рекомендую не разбрасывать простой запрос хранимой процедурой:

Если вы зацикливаете хранимые процедуры над чем-то, что запрос может выполнять очень неэффективно.

Такэта процедура может быть заменена одним запросом:

SELECT Room_type, No_of_room, ArrivalDate, DepartDate, state
FROM reservation_temp
WHERE Reservation_is_done = 1
      AND state != 0
      AND ArrivalDate <= {arrivedate}
      AND {enddate} < DepartDate

Действительно ли booking_temp - временная таблица?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...