[英]MySQL Stored Procedure Loop Increment Date In Select Query Returns Last Date
我有一個存儲過程,它會增加選擇查詢中的特定日期。 我需要獲取遞增日期變量的當前值以及其他字段。 但是查詢始終僅返回最后一個遞增的日期。 您能告訴我錯誤在哪里嗎?
存儲過程:
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');
[編輯]我需要它來輸出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;
我建議您不要使用存儲過程來膨脹簡單的查詢:
如果您在某個過程中循環存儲過程,則查詢的效率可能非常低。
因此,此過程可以替換為單個查詢:
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
Reservation_temp真的是臨時表嗎?
如我的評論中所述,問題是由SELECT
語句在增加nextDate
之前迭代一天的行集引起的。 結果,您的過程每天將執行多個SELECT
語句,並從上次執行的查詢返回結果。
即:
SELECT day1;
SELECT day2;
要以我認為您希望實現的方式解決此問題,一種方法是使用臨時表存儲每天檢索到的記錄,直到處理完每一天為止,然后從臨時表中檢索值。
但是,您需要為ArrivalDate,DepartDate和state更好地定義
GROUP BY
列。 由於MySQL 5.7+默認情況下啟用了ONLY_FULL_GROUP_BY
,因此會出錯。 我已經使用MIN
,MAX
並將state
添加到分組中以防止錯誤。或者,在列上顯式使用
ANY_VALUE()
,以允許MySQL在每個未聚合的組中選擇一個值。 [原文如此]
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和ID 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 |
您可能需要看一下此討論: 從日期范圍生成天數
使用討論中的一些查詢,您可以獲取日期范圍內的日期列表。 然后,僅內部/左側加入您的數據即可獲得所需的內容。
使用我的實現(我有helper table +視圖,但這不是必需的),生成的查詢看起來像這樣:
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.