【问题标题】:Add rows for each day that lies in a period in MYSQL为 MYSQL 中某个时间段内的每一天添加行
【发布时间】:2020-10-22 13:37:43
【问题描述】:

我正在处理“预订”表 -

我想在此表中添加“date_of_stay”列,其中 date_of_stay 将根据“nights”列给出的晚数存储 booking_id 停留期间的每个日期。 例如-

booking_id    booking_date        nights    date_of_stay

5001        Thu, 03 Nov 2016       7        Thu, 03 Nov 2016
5001        Thu, 03 Nov 2016       7        Fri, 04 Nov 2016
5001        Thu, 03 Nov 2016       7        Sat, 05 Nov 2016
5001        Thu, 03 Nov 2016       7        Sun, 06 Nov 2016
5001        Thu, 03 Nov 2016       7        Mon, 07 Nov 2016
5001        Thu, 03 Nov 2016       7        Tue, 08 Nov 2016
5001        Thu, 03 Nov 2016       7        Wed, 09 Nov 2016
5002        Thu, 03 Nov 2016       2        Thu, 03 Nov 2016
5002        Thu, 03 Nov 2016       2        Fri, 04 Nov 2016

在不改变表格的情况下,以这种方式查看我的表格的最简单方法是什么?

【问题讨论】:

标签: mysql sql select


【解决方案1】:

使用递归 CTE:

with cte as (
      select booking_id, booking_date, nights, 1 as n
      from t
      union all
      select booking_id, booking_date, nights, 1 + n
      from cte
      where n < nights
     )
select *
from cte;

【讨论】:

    【解决方案2】:

    根据article,您可以使用下一个查询:

    select booking.*, date_of_stay
    from (
      select adddate('2015-01-01', t3*1000 + t2*100 + t1*10 + t0) date_of_stay from
        (select 0 t0 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0,
        (select 0 t1 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1,
        (select 0 t2 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2,
        (select 0 t3 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3
    ) v
    join booking ON date_of_stay between 
        booking.booking_date and date_add(booking.booking_date, interval nights-1 day)
    order by booking_id, date_of_stay
    ;
    

    上述查询也适用于 MYSQL 5 和 8。对区间内的所有日期都有效:

    select '2015-01-01' from_date, adddate('2015-01-01',9*1000 + 9*100 + 9*10 + 9) to_date;
    +------------+------------+
    |  from_date |    to_date |
    +------------+------------+
    | 2015-01-01 | 2042-05-18 |
    +------------+------------+
    

    这里查询可以测试SQLize.online

    【讨论】:

      【解决方案3】:

      您可以使用递归 CTE 来做到这一点:

      WITH RECURSIVE cte AS (
        SELECT booking_id, booking_date, nights, 0 nr, 
               STR_TO_DATE(booking_date, '%a, %d %b %Y') date_of_stay
        FROM booking
        UNION ALL
        SELECT booking_id, booking_date, nights, nr + 1,
               date_of_stay + interval 1 day
        FROM cte       
        WHERE nr < nights - 1       
      )
      SELECT c.booking_id, c.booking_date, c.nights, 
             DATE_FORMAT(c.date_of_stay, '%a, %d %b %Y') date_of_stay
      FROM cte c
      ORDER BY c.booking_id, c.date_of_stay
      

      请参阅demo
      结果:

      > booking_id | booking_date     | nights | date_of_stay    
      > ---------: | :--------------- | -----: | :---------------
      >       5001 | Thu, 03 Nov 2016 |      7 | Thu, 03 Nov 2016
      >       5001 | Thu, 03 Nov 2016 |      7 | Fri, 04 Nov 2016
      >       5001 | Thu, 03 Nov 2016 |      7 | Sat, 05 Nov 2016
      >       5001 | Thu, 03 Nov 2016 |      7 | Sun, 06 Nov 2016
      >       5001 | Thu, 03 Nov 2016 |      7 | Mon, 07 Nov 2016
      >       5001 | Thu, 03 Nov 2016 |      7 | Tue, 08 Nov 2016
      >       5001 | Thu, 03 Nov 2016 |      7 | Wed, 09 Nov 2016
      >       5002 | Thu, 03 Nov 2016 |      2 | Thu, 03 Nov 2016
      >       5002 | Thu, 03 Nov 2016 |      2 | Fri, 04 Nov 2016
      

      【讨论】:

        猜你喜欢
        • 2018-03-27
        • 1970-01-01
        • 2019-05-23
        • 2021-05-20
        • 1970-01-01
        • 1970-01-01
        • 2018-12-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多