Oracle SQL - 合并重叠的期间

news2024/9/23 5:35:17
  • 数据和目标

有如下数据存储了各组件的有效期间(此处起止日期用数字代替以便查阅),目标为将有重叠的期间合并到一起。

SQL> SELECT * FROM demo_eff_periods;

COMPONENT_ITEM_ID EFFECTIVITY_DATE DISABLE_DATE
----------------- ---------------- ------------
                1             1000         1999
                1             1500         3000
                1             3000         3999
                1             4000         4999
                2             1000         4999
                2             2000         3999
                3             1000         1999
                3             1500         2999
                3             1000         3999
                4             1000         1999
                4             2000         2999
                4             3000         3999
                5             1000         1999
                5             1000         1999
                5             4000         4999

15 rows selected

将数据用下图表示,除组件1的第二段区间为闭区间,其它均为左闭右开。

  •  例程一:转化为连续日期合并

先使用递归语法把每段期间拆解出具体的每一天,再将连续的日期整合为新区间。

这里使用dense_rank是因为可能有重复的日期出现。

如果出现上一期间的结束日期与下一期间的开始日期刚好连续的情况,这个方法将会把这两个区间合并到一起。

SQL> SELECT component_item_id,
  2         MIN(new_date) effectivity_date,
  3         MAX(new_date) disable_date
  4    FROM (SELECT dep.component_item_id,
  5                 dep.effectivity_date + LEVEL - 1 new_date,
  6                 dense_rank() over(PARTITION BY dep.component_item_id ORDER BY dep.effectivity_date + LEVEL) dr
  7            FROM demo_eff_periods dep
  8          CONNECT BY LEVEL + dep.effectivity_date - 1 <= dep.disable_date
  9                 AND PRIOR dep.rowid = dep.rowid
 10                 AND PRIOR sys_guid() IS NOT NULL)
 11   GROUP BY component_item_id, new_date - dr;

COMPONENT_ITEM_ID EFFECTIVITY_DATE DISABLE_DATE
----------------- ---------------- ------------
                1             1000         4999
                2             1000         4999
                3             1000         3999
                4             1000         3999
                5             1000         1999
                5             4000         4999

6 rows selected
  • 例程二:递归串联区间合并

使用RSF语法,先找到所有不被其它区间包含的期间开始日期,再递归串联后续区间,最终得以合并。

将SQL中注释的部分解除,则可实现如例程一的进一步合并连续区间的效果。

SQL> WITH rsf_eff_periods(component_item_id, effectivity_date, disable_date) AS
  2   (SELECT dep.component_item_id, dep.effectivity_date, dep.disable_date
  3      FROM demo_eff_periods dep
  4     WHERE NOT EXISTS
  5     (SELECT 1
  6              FROM demo_eff_periods dep0
  7             WHERE dep0.component_item_id = dep.component_item_id
  8               AND dep0.effectivity_date < dep.effectivity_date
  9               AND dep0.disable_date >= dep.effectivity_date /*- 1*/)
 10    UNION ALL
 11    SELECT rep.component_item_id, rep.effectivity_date, dep.disable_date
 12      FROM rsf_eff_periods rep, demo_eff_periods dep
 13     WHERE rep.component_item_id = dep.component_item_id
 14       AND rep.disable_date >= dep.effectivity_date /*- 1*/
 15       AND rep.disable_date < dep.disable_date)
 16  SELECT component_item_id, effectivity_date, MAX(disable_date) disable_date
 17    FROM rsf_eff_periods
 18   GROUP BY component_item_id, effectivity_date;

COMPONENT_ITEM_ID EFFECTIVITY_DATE DISABLE_DATE
----------------- ---------------- ------------
                1             1000         3999
                1             4000         4999
                2             1000         4999
                3             1000         3999
                4             1000         1999
                4             2000         2999
                4             3000         3999
                5             1000         1999
                5             4000         4999

9 rows selected

 CONNECT BY写法:

SELECT component_item_id, effectivity_date, MAX(disable_date) disable_date
  FROM (SELECT dep.component_item_id,
               connect_by_root effectivity_date effectivity_date,
               dep.disable_date
          FROM demo_eff_periods dep
         START WITH NOT EXISTS
         (SELECT 1
                       FROM demo_eff_periods dep0
                      WHERE dep0.component_item_id = dep.component_item_id
                        AND dep0.effectivity_date < dep.effectivity_date
                        AND dep0.disable_date >= dep.effectivity_date /*- 1*/
                     )
        CONNECT BY PRIOR dep.component_item_id = dep.component_item_id
               AND PRIOR dep.disable_date >= dep.effectivity_date /*- 1*/
               AND PRIOR dep.disable_date < dep.disable_date)
 GROUP BY component_item_id, effectivity_date;
  • 例程三:区间端点排序重组

分别找到不被其它期间包含的开始日期和结束日期,即合并后应得的区间端点,两类端点(开始和结束)分别排序,同位次的端点即组成新区间。

这里使用dense_rank是因为可能有重复的日期出现。

将SQL中注释的部分解除,则可实现如例程一的进一步合并连续区间的效果。

SQL> SELECT component_item_id,
  2         MIN(new_date) effectivity_date,
  3         MAX(new_date) disable_date
  4    FROM (SELECT dep.component_item_id,
  5                 dep.effectivity_date new_date,
  6                 dense_rank() over(PARTITION BY dep.component_item_id ORDER BY dep.effectivity_date) dr
  7            FROM demo_eff_periods dep
  8           WHERE NOT EXISTS
  9           (SELECT 1
 10                    FROM demo_eff_periods dep0
 11                   WHERE dep0.component_item_id = dep.component_item_id
 12                     AND dep0.effectivity_date < dep.effectivity_date
 13                     AND dep0.disable_date >= dep.effectivity_date /*- 1*/)
 14          UNION ALL
 15          SELECT dep.component_item_id,
 16                 dep.disable_date new_date,
 17                 dense_rank() over(PARTITION BY dep.component_item_id ORDER BY dep.disable_date) dr
 18            FROM demo_eff_periods dep
 19           WHERE NOT EXISTS
 20           (SELECT 1
 21                    FROM demo_eff_periods dep0
 22                   WHERE dep0.component_item_id = dep.component_item_id
 23                     AND dep0.effectivity_date <= dep.disable_date /*+ 1*/
 24                     AND dep0.disable_date > dep.disable_date))
 25   GROUP BY component_item_id, dr;

COMPONENT_ITEM_ID EFFECTIVITY_DATE DISABLE_DATE
----------------- ---------------- ------------
                1             1000         3999
                1             4000         4999
                2             1000         4999
                3             1000         3999
                4             1000         1999
                4             2000         2999
                4             3000         3999
                5             1000         1999
                5             4000         4999

9 rows selected
  • 例程四:区间端点排序重组(减少扫描表次数)

对于每一个原始期间,如有比自己早开始的期间其结束日期比自己的开始日期还大,则自己的开始日期将被吞并;如有比自己晚结束的期间其开始日期比自己的结束日期还小,则自己的结束日期将被吞并。

筛选出合并后应得的区间端点后,两类端点(开始和结束)分别排序,同位次的端点即组成新区间。

这里使用dense_rank是因为可能有重复的日期出现。

将SQL中注释的部分解除,则可实现如例程一的进一步合并连续区间的效果。

SQL> SELECT component_item_id,
  2         MIN(new_date) effectivity_date,
  3         MAX(new_date) disable_date
  4    FROM (SELECT component_item_id,
  5                 new_date,
  6                 dense_rank() over(PARTITION BY component_item_id, date_pos ORDER BY new_date) dr
  7            FROM (SELECT dep.component_item_id,
  8                         CASE
  9                           WHEN MAX(dep.disable_date)
 10                            over(PARTITION BY dep.component_item_id ORDER BY
 11                                     dep.effectivity_date
 12                                     RANGE BETWEEN unbounded preceding AND 1
 13                                     preceding) >= dep.effectivity_date /*- 1*/ THEN
 14                            NULL
 15                           ELSE
 16                            dep.effectivity_date
 17                         END AS effectivity_date,
 18                         CASE
 19                           WHEN MIN(dep.effectivity_date)
 20                            over(PARTITION BY dep.component_item_id ORDER BY
 21                                     dep.disable_date DESC
 22                                     RANGE BETWEEN unbounded preceding AND 1
 23                                     preceding) <= dep.disable_date /*+ 1*/ THEN
 24                            NULL
 25                           ELSE
 26                            dep.disable_date
 27                         END AS disable_date
 28                    FROM demo_eff_periods dep)
 29          UNPIVOT(new_date FOR date_pos IN(effectivity_date, disable_date)))
 30   GROUP BY component_item_id, dr;

COMPONENT_ITEM_ID EFFECTIVITY_DATE DISABLE_DATE
----------------- ---------------- ------------
                1             1000         3999
                1             4000         4999
                2             1000         4999
                3             1000         3999
                4             1000         1999
                4             2000         2999
                4             3000         3999
                5             1000         1999
                5             4000         4999

9 rows selected

更多方法,欢迎大家讨论

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2057369.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring GateWay自定义断言工厂

文章目录 概要整体架构流程最终的处理效果小结 概要 我们在线上系统部署了&#xff0c;灰度环境和生产环境时&#xff0c;可以通过自定义断言工厂去将请求需要路由到灰度环境的用户调用灰度的的服务集群&#xff0c;将正常的用户调用正常集群。 这样&#xff0c;我们可以在上线…

【UCB CS61C】Lecture 1 - Number Representation 数制

目录 进制的定义常用的进制与换算十进制到二进制的转换二进制到十六进制、十六进制到二进制的转换二进制向 n 进制的转换 有符号数处理&#xff08;Signed Representation&#xff09;无符号整数&#xff08;Unsigned Integers&#xff09;有符号整数&#xff08;Signed Interg…

亚德诺(ADI)超静音步进电机驱动芯片——TMC2209

芯品快报:德州仪器(TI)的高性能、集成式的双全桥电机驱动器——DRV8412 芯品快报:亚德诺(ADI)超静音步进电机驱动芯片——TMC2209 原创 IPBrain平台君 集成电路大数据平台 2024年08月16日 19:18 北京 平台君今天给大家介绍一款亚德诺(ADI)公司的用于两相步进电机的超…

Elasticsearch 使用误区之四——不合理的使用 track_total_hits

0、企业级实战问题 在使用 Elasticsearch 进行搜索时&#xff0c;我们常常关心匹配查询的文档总数而将 track_total_hits 设置为 true&#xff0c;如下截图所示&#xff0c;在数据量非常大的情况下这种检索导致的问题是&#xff1a;查询特别慢&#xff0c;聚合会更慢&#xff0…

RKNN在转换过程中的均值和方差设置问题

为什么ONNX转RKNN要匹配均值和方差&#xff1f; 因为不匹配精度会下降&#xff01;&#xff01;&#xff01; 一般的类似于YOLO模型 YOLO模型在ONNX转RKNN时rknn.config设置为 一些其他模型将数据送入模型时会进行前处理&#xff0c;前处理会设置均值和方差&#xff0c;则在转…

【Nginx】实现 FastCGI

为什么会有 FastCGI &#xff1f; CGI 协议虽然解决了语言解析器和 Web Server 之间通讯的问题&#xff0c;但是它的效率很低&#xff0c;因为 Web Server每收到一个请求都会创建一个CGI 进程&#xff0c; PHP 解析器都会解析 php.ini 文件&#xff0c;初始化环境&#xff0c…

LCP142 环形链表[leetcode-7]

LCP142 环形链表 先上结果 前排提醒&#xff0c;本文有两种解法&#xff0c;和原理分析 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次…

数据结构与算法 - 设计

1. LRU缓存 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存int get(int key) 如果关键字 key 存在于缓存中&#xff0c;则返回关键字的值&#xff0…

0819、0820梳理及一些面试题梳理

一、抓包分析 二、HTTP服务器 三、动态库与静态库 四、一些面试题 指针数组和数组指针的区别&#xff1a;指针数组本质是一个数组&#xff0c;只是数组中存储的是指针变量。数组指针存储的是该数组的起始地址&#xff0c;对该指针来说每偏移一个单位就是偏移了一整个数组的地…

如何寻找专业精密机械零件代加工工厂

在现代工业生产中&#xff0c;精密机械零件的加工质量直接关系到产品的性能和可靠性。因此&#xff0c;寻找一家专业的精密机械零件代加工工厂至关重要。以下时利和整理分享的一些关于寻找专业精密机械零件代加工工厂的关键步骤和要点&#xff0c;帮助你找到合适的合作伙伴。 首…

想投资现货黄金?在TMGM开户需要多少钱?

最近&#xff0c;越来越多的人开始关注黄金投资&#xff0c;希望通过黄金来对冲风险、保值增值。而选择一家可靠的交易平台是进行黄金投资的第一步。TMGM作为全球知名的外汇交易商&#xff0c;也为投资者提供了黄金交易服务。那么&#xff0c;在TMGM开户投资黄金&#xff0c;需…

尚硅谷VUE项目实战,前端项目-尚品汇2

尚硅谷VUE项目实战&#xff0c;前端项目-尚品汇2 1、路由传参 2、重写push

数字转化为千位符形式, 百分比形式

Intl.NumberFormat 千位符&#xff1a; function formatAsRMB(num){return new Intl.NumberFormat(zh-CN,{style: decimal, //将数字格式化为十进制数currency: CNY, // 货币为人民币minimumFractionDigits: 0 // 表示不显示小数部分}).format(num)}const number 12345678co…

【C++进阶学习】第十四弹——特殊类设计——探寻各种情况下类的应用

前言&#xff1a; C类是C很重要的一个部分&#xff0c;在很多应用场景中都发挥着十分重要的作用&#xff0c;今天我们来讲解几个特殊场景下类的应用 目录 一、特殊类&#xff1a;只能在栈/堆上创建对象 1. 只在栈上创建对象 2. 只在堆上创建对象 二、特殊类&#xff1a;不能…

8.20 QT

1.思维导图 2. 头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTime> #include <QTimerEvent> #include <QTextToSpeech>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidge…

Zookeeper中 Server 服务器的四种工作状态详解

Zookeeper中 Server 服务器的四种工作状态详解 1. LOOKING2. FOLLOWING3. LEADING4. OBSERVING&#xff08;3.3.0及以后版本&#xff09; &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; ZooKeeper集群中的服务器主要存在以下四种工作状态&a…

32位入门级MCU(ARM Cortex-M3内核)STM32F103系列

推荐: 32位入门级MCU(ARM Cortex-M3内核)中的六边形战士——STM32F103系列 为什么MCU中需要ADC模块 原创 IPBrain平台君 集成电路大数据平台 2024年08月19日 19:18 北京 自从平台君发布了几期关于MCU的文章之后,后台有很多小伙伴们留言。其中有位读者问平台君:平台君,…

python构建一个web程序

from flask import Flaskapp Flask(__name__)app.route(/) def hello_world():return 欢迎来到我的Python Web程序!if __name__ __main__:app.run(debugTrue)1、安装flask D:\Users\USER\PycharmProjects\pythonProject1\p01>pip install flask WARNING: Ignoring invalid…

LLM才硬件(显存)需求

参考&#xff1a; https://www.hardware-corner.net/guides/computer-to-run-llama-ai-model/ GitHub - hiyouga/LLaMA-Factory: Efficiently Fine-Tune 100 LLMs in WebUI (ACL 2024) 直观的一个表&#xff1a;

多模态学习Multimodal Learning:人工智能中的多模态原理与技术介绍初步了解

多模态学习&#xff08;Multimodal Learning&#xff09;是机器学习中的一个前沿领域&#xff0c;旨在综合处理和理解来自不同模态的数据。模态可以包括文本、图像、音频、视频等。随着数据多样性和复杂性增加&#xff0c;多模态学习在自然语言处理、计算机视觉、语音识别等领域…