从日期中选择时段

Posted

技术标签:

【中文标题】从日期中选择时段【英文标题】:select periods from date 【发布时间】:2018-02-19 09:12:43 【问题描述】:

我在从缺勤列表中选择一个接一个的缺勤并将它们分组到时段时遇到问题。

date_from (data_od)  date_to(data_do)
--------------------------
18/08/01 -  18/08/15
18/08/16 -  18/08/20
18/08/21 -  18/08/31
18/09/01 -  18/09/08
18/05/01 -  18/05/31
18/06/01 -  18/06/30
18/03/01 -  18/03/18
18/02/14 -  18/02/28

上面是缺勤列表,其结果应该是一个表格:

date_from (data_od)  date_to(data_do)
--------------------------
18/08/01    18/09/08
18/05/01    18/06/30
18/02/14    18/03/18

目前,我做了类似的事情,但我只研究了两个:(

 SELECT u1.data_od,u2.data_do
        FROM l_absencje u1 CROSS APPLY
          (SELECT *  FROM l_absencje labs
              WHERE labs.prac_id=u1.prac_id AND 
               TRUNC(labs.data_od) = TRUNC(u1.data_do)+1
             ORDER BY id DESC FETCH FIRST 1 ROWS ONLY
          ) u2 where u1.prac_id=1067 ;

然后给我:

18/08/01    18/08/20 bad
18/08/16    18/08/31 bad
18/08/21    18/09/08 bad
18/05/01    18/06/30 good 
18/02/14    18/03/18 good

【问题讨论】:

有多种方法可以解决gaps-and-island问题; this looks like a similar scenario 但您可能会在该标签下找到更好的方法。 【参考方案1】:

您可以结合使用LAG()LEAD()LAST_VALUE() 分析函数:

SQL Fiddle

Oracle 11g R2 架构设置

CREATE TABLE absences ( date_from, date_to ) AS
SELECT DATE '2018-08-01', DATE '2018-08-15' FROM DUAL UNION ALL
SELECT DATE '2018-08-16', DATE '2018-08-20' FROM DUAL UNION ALL
SELECT DATE '2018-08-21', DATE '2018-08-31' FROM DUAL UNION ALL
SELECT DATE '2018-09-01', DATE '2018-09-08' FROM DUAL UNION ALL
SELECT DATE '2018-05-01', DATE '2018-05-31' FROM DUAL UNION ALL
SELECT DATE '2018-06-01', DATE '2018-06-30' FROM DUAL UNION ALL
SELECT DATE '2018-03-01', DATE '2018-03-18' FROM DUAL UNION ALL
SELECT DATE '2018-02-14', DATE '2018-02-28' FROM DUAL;

查询 1

SELECT *
FROM   (
  SELECT CASE
         WHEN date_to IS NOT NULL
         THEN LAST_VALUE( date_from ) IGNORE NULLS
                OVER( ORDER BY ROWNUM )
         END AS date_from,
         date_to
  FROM   (
    SELECT CASE date_from
           WHEN LAG( date_to ) OVER ( ORDER BY date_to )
                + INTERVAL '1' DAY
           THEN NULL
           ELSE date_from
           END AS date_from,
           CASE date_to
           WHEN LEAD( date_from ) OVER ( ORDER BY date_from )
                - INTERVAL '1' DAY
           THEN NULL
           ELSE date_to
           END AS date_to
    FROM   absences
  )
)
WHERE  date_from IS NOT NULL
AND    date_to IS NOT NULL

Results

|            DATE_FROM |              DATE_TO |
|----------------------|----------------------|
| 2018-02-14T00:00:00Z | 2018-03-18T00:00:00Z |
| 2018-05-01T00:00:00Z | 2018-06-30T00:00:00Z |
| 2018-08-01T00:00:00Z | 2018-09-08T00:00:00Z |

【讨论】:

以上是关于从日期中选择时段的主要内容,如果未能解决你的问题,请参考以下文章

日期分时段校验规则

每个时段的 MySQL 查询小计,小时从当天下午 2 点到第二天下午 2 点

R语言ggplot2可视化:可视化所有日期不同时段任务的持续时间将持续时间绘制成一条线(起始时间到结束时间),y轴表示活动发生的日期,x轴表示以小时为单位的时间

R语言ggplot2可视化:可视化所有日期不同时段任务的持续时间将持续时间绘制成一条线(起始时间到结束时间),y轴表示活动发生的日期,x轴表示以小时为单位的时间适应时间段跨越多天的情况

日语时段--时间序列中的一段距离

如何限制用户从日期选择器中选择过去的日期?