选择查询中的MySQL存储过程循环递增日期返回最后一个日期

时间:2019-02-22 01:48:16

标签: mysql stored-procedures

我有一个存储过程,该过程在选择查询中增加特定日期。我需要获取递增日期变量的当前值以及其他字段。但是查询始终仅返回最后一个递增的日期。您能告诉我错误在哪里吗?。

存储过程:

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 :(得分:0)

我建议您不要使用存储过程来膨胀简单的查询:

如果您在存储过程中循环访问某个内容,查询可能会非常低效。

因此,此过程可以用一个查询替换:

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真的是临时表吗?

答案 1 :(得分:0)

如我的评论中所述,此问题是由dgof语句在增加SELECT之前遍历一天的行集引起的。结果,您的过程每天将执行多个nextDate语句,并从上次执行的查询返回结果。

即:

SELECT

要以我认为您希望实现的方式解决此问题,一种方法是使用临时表存储每天检索到的记录,直到处理完每一天为止,然后从临时表中检索值。 / p>

  

但是,您需要为ArrivalDate,DepartDate和state更好地定义SELECT day1; SELECT day2; 列。   由于MySQL 5.7+默认启用了GROUP BY,因此会出错。我已使用ONLY_FULL_GROUP_BYMIN并将MAX添加到分组中以防止出错。

     

或者在列上显式使用state,以允许MySQL在每个组中选择一个尚未聚合的值。   [sic]

ANY_VALUE()

使用的数据集(请注意,ID 1和2具有不同的DepartDate值)

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

结果

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 | 

答案 2 :(得分:0)

您可能需要查看以下讨论: generate days from date range

使用讨论中的一些查询,您可以获取日期范围内的日期列表。然后,只需将内部/左侧的数据连接起来,便可以得到想要的东西。

使用我的实现(我有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