社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  DATABASE

MySQL或MariaDB将单行中的日期范围扩展为多个系列行

Gipyo.Choi • 3 年前 • 1139 次点击  

示例表如下:,

CREATE TABLE TIMEOFF_INFO (
  TIMEOFF_ID INT PRIMARY KEY,
  TIMEOFF_BEGIN DATE NOT NULL,
  TIMEOFF_END DATE NOT NULL
)

以及下面的示例行,

+------------+---------------+-------------+
| timeoff_id | timeoff_begin | timeoff_end |
+------------+---------------+-------------+
|      1     | 2021-10-01    | 2021-10-02   |
+------------+---------------+-------------+
|      2     | 2021-11-15    | 2021-11-15  |
+------------+---------------+-------------+
|      3     | 2021-12-18    | 2021-12-20  |
+------------+---------------+-------------+

我想得到的是将上表转换为下表,这样我就可以使用范围内的每个日期加入。

2021-10-01 (id: 1's begin date)
2021-10-02 (id: 1's end date)
2021-11-15 (id: 2's begin and end date)
2021-12-18 (id: 3's begin date)
2021-12-19
2021-12-20 (id: 3's end date)

有没有办法将单行中的日期范围扩展到一系列日期行?

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/128961
 
1139 次点击  
文章 [ 3 ]  |  最新文章 3 年前
scaisEdge
Reply   •   1 楼
scaisEdge    3 年前

你可以在同一张桌子上使用一个工会

    select id, timeoff_begin timeoff, concat(id, ' begin date') msg
    from TIMEOFF_INFO
    union all 
    select id, timeoff_end, concat(id, ' end date') 
    from TIMEOFF_INFO
    order by id, timeoff
P.Salmon
Reply   •   2 楼
P.Salmon    3 年前

与@akina差不多,但不那么复杂。此处,cte仅用于识别日期差异大于;1然后加入日期表并联合。开始日期、中间日期和结束日期由一个用于订购的标志标识。 这可以在没有cte的情况下完成,但cte确实有助于澄清(我认为), 注:我对样本数据进行了轻微修改

drop table if exists t;
create table t
(timeoff_id int, timeoff_begin date, timeoff_end date);
insert into t values
(      1     , '2020-10-01'    , '2020-10-05'),  
(      2     , '2020-11-15'    , '2020-11-15'),  
(      3     , '2020-12-18'    , '2020-12-21');  

with cte as
(select 2 as beg,timeoff_id , timeoff_begin, timeoff_end ,datediff(timeoff_end, timeoff_begin) diff 
from t
where datediff(timeoff_end, timeoff_begin) > 1)
select cte.beg,cte.timeoff_id,dates.dte
from cte 
join dates where dates.dte > cte.timeoff_begin and dates.dte <= date_add(cte.timeoff_begin, interval cte.diff -1 day) 
union all
(select 1 as beg,timeoff_id , timeoff_begin dt from t 
union all
select 3 ,timeoff_id , timeoff_end from t 
)
order by timeoff_id, beg,dte;

+-----+------------+------------+
| beg | timeoff_id | dte        |
+-----+------------+------------+
|   1 |          1 | 2020-10-01 |
|   2 |          1 | 2020-10-02 |
|   2 |          1 | 2020-10-03 |
|   2 |          1 | 2020-10-04 |
|   3 |          1 | 2020-10-05 |
|   1 |          2 | 2020-11-15 |
|   3 |          2 | 2020-11-15 |
|   1 |          3 | 2020-12-18 |
|   2 |          3 | 2020-12-19 |
|   2 |          3 | 2020-12-20 |
|   3 |          3 | 2020-12-21 |
+-----+------------+------------+
Akina
Reply   •   3 楼
Akina    3 年前
WITH RECURSIVE
daterange AS ( SELECT MIN(TIMEOFF_BEGIN) dStart, MAX(TIMEOFF_END) dEnd
               FROM TIMEOFF_INFO ),
calendar AS ( SELECT dStart `date` 
              FROM daterange
              UNION ALL
              SELECT `date` + INTERVAL 1 DAY
              FROM calendar
              WHERE `date` < ( SELECT dEnd FROM daterange ) )
SELECT calendar.`date`
FROM calendar
WHERE EXISTS ( SELECT NULL
               FROM TIMEOFF_INFO 
               WHERE calendar.`date` BETWEEN TIMEOFF_INFO.TIMEOFF_BEGIN AND TIMEOFF_INFO.TIMEOFF_END )

需要MariaDB 10.2+或MySQL 8+。