SQL时间错位与还原生成案例

需求描述

1 原表T1某条记录(记做r1,相邻下一条为r2)的下一行记录的STARTDATE小于上一行ENDDATE,针对这样的记录做转换即:

r1的STARTDATE保持不变,ENDDATE为r1的STARTDATE-1

r2的STARTDATE为r1的ENDDATE,ENDDATE为r1的ENDDATE

2 如果原表T1不存在相邻行“时间重叠”(即为1的定义)时保持原有数据不变。

# 文本版
#T1
seq id  startdate   enddate     num
1   1   2021-04-20  2021-05-03  200
2   1   2021-05-01  2021-05-24  100
3   1   2021-05-18  2021-05-31  69
4   1   2021-05-20  2021-07-31  34
5   1   2021-08-05  2021-08-25  45
6   1   2021-08-15  2021-09-25  65#输出结果
ID STARTDATE    ENDDATE     NUM
1  2021-04-20   2021-04-30  200
1  2021-05-01   2021-05-02  300
1  2021-05-03   2021-05-17  100
1  2021-05-18   2021-05-19  169
1  2021-05-20   2021-05-23  203
1  2021-05-24   2021-05-30  103
1  2021-05-31   2021-07-30  34
1  2021-08-05   2021-08-14  45
1  2021-08-15   2021-08-25  110
1  2021-08-26   2021-09-25  65

思路概述

#1 需求延展
SEQ     ID      STARTDATE       ENDDATE         NUM
1   1   2021-04-20  2021-05-03  200
2   1   2021-05-01  2021-05-24  100
3   1   2021-05-18  2021-05-31  69
4   1   2021-05-20  2021-07-31  34
这里第4条记录同时叠加在第2和3条记录里。#2 思路概述
1) T0 通过上下行函数生成的时间序列
id      new_DATE        nextSTARTDATE   preEndDATE     rn
1   2021-05-24              2021-05-03  1
1   2021-05-03  2021-05-24  2021-05-01  2
1   2021-05-01  2021-05-03  2021-04-20  3
1   2021-04-20  2021-05-01              42) last 取出T0里的最后一条记录,为后面的矫正做准备。
new_Date        preENDDATE      id
2021-05-24  2021-05-03  13) normal 取出原始数据里不会出现时间叠加的记录,为后面的矫正做准备。
当前演示数据无记录,代码加注释可浮现。4)T_Serial 统一定义STARTDATE、ENDDATE,首次修正T0。
id      STARTDATE       ENDDATE
1   2021-04-20  2021-04-30
1   2021-05-01  2021-05-03
1   2021-05-04  2021-05-245) T2 对时间没有重叠的记录进行修正(删除T0对应值,更新对应ENDDATE)。
当前示例结果集为空,即无需要修正。6) T2关联T1(原始表),汇总后取得最终值
STARTDATE   ENDDATE     NUM
2021-04-20  2021-04-30  200
2021-05-01  2021-05-03  300
2021-05-04  2021-05-24  100

SQL代码

-- 当前演示版本是Mysql 8.0.23,支持CTE、窗口函数的SQL Server、Oracle需要修改Order by和ADDDATE处语法。
-- Step0 创建表并初始化数据
DROP TABLE IF EXISTS test_ShenLiang2025;
CREATE TABLE test_ShenLiang2025 (seq int DEFAULT NULL,id int DEFAULT NULL,STARTDATE date DEFAULT NULL,ENDDATE date DEFAULT NULL,NUM int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;INSERT INTO test_ShenLiang2025 VALUES ('1', '1', '2021-04-20', '2021-05-03', '200');
INSERT INTO test_ShenLiang2025 VALUES ('2', '1', '2021-05-01', '2021-05-24', '100');
INSERT INTO test_ShenLiang2025 VALUES ('3', '1', '2021-05-18', '2021-05-31', '69');
INSERT INTO test_ShenLiang2025 VALUES ('4', '1', '2021-05-20', '2021-07-31', '34');
INSERT INTO test_ShenLiang2025 VALUES ('5', '1', '2021-08-05', '2021-08-25', '45');
INSERT INTO test_ShenLiang2025 VALUES ('6', '1', '2021-08-15', '2021-09-25', '65');-- Step1 构建临时结果集以生成时间序列。
WITH T0 AS(
SELECT id, new_DATE,LEAD(NEW_DATE,1) OVER (PARTITION BY ID ORDER BY NEW_DATE ) nextSTARTDATE,LAG(NEW_DATE,1) OVER (PARTITION BY ID ORDER BY NEW_DATE ) preENDDATE,ROW_NUMBER()OVER(PARTITION BY ID ORDER BY new_DATE DESC) rnFROM(SELECT DISTINCT ID,STARTDATE new_DATE  FROM test_ShenLiang2025    WHERE seq in (1,2) -- 可加注释验证,当前仅取原表里2条记录UNIONSELECT DISTINCT ID,ENDDATE new_DATE FROM test_ShenLiang2025WHERE seq in (1,2) -- 可加注释验证,当前仅取原表里2条记录ORDER BY new_DATE )A
),last AS
( SELECT new_DATE,preENDDATE,id
FROM T0
WHERE nextSTARTDATE IS NULL
),normal AS
(SELECT * FROM(SELECT id, ENDDATE,LEAD(STARTDATE,1) OVER (PARTITION BY ID ORDER BY ENDDATE ) nextSTARTDATE,LAG(ENDDATE,1) OVER (PARTITION BY ID ORDER BY ENDDATE ) preENDDATEFROM test_ShenLiang2025)AWHERE ENDDATE > preENDDATE AND ENDDATE < nextSTARTDATE
),T_Serial AS (SELECT ID,ADDDATE(preENDDATE, INTERVAL 1 DAY ) STARTDATE,
new_DATE ENDDATE
FROM last UNIONSELECT bottom_2.ID,bottom_2.new_DATE STARTDATE,
CASE WHEN rn =3 THEN bottom_2.nextSTARTDATE ELSE ADDDATE(bottom_2.nextSTARTDATE, INTERVAL -1 DAY ) END ENDDATE
FROM last
JOIN T0 bottom_2
ON bottom_2.nextSTARTDATE<=last.preENDDATE AND bottom_2.id = last.id
),T2 AS(
SELECT B.ID,B.STARTDATE,B.ENDDATE FROM(SELECT A.*,ROW_NUMBER()OVER(PARTITION BY ID,STARTDATE ORDER BY ENDDATE) rnFROM(SELECT A.ID,A.STARTDATE,A.ENDDATEFROM T_Serial ALEFT JOIN normal BON A.STARTDATE = B.ENDDATE AND A.ID = B.IDWHERE B.ENDDATE IS NULLUNION SELECT A.ID,A.STARTDATE,B.ENDDATE   FROM T_Serial AINNER JOIN normal BON ADDDATE(A.ENDDATE, INTERVAL 1 DAY ) = B.ENDDATE AND A.ID = B.ID          )A)B WHERE rn =1
)-- Step2 时间序列关联原表生成NUM字段。
SELECT T2.STARTDATE,T2.ENDDATE,SUM(T1.NUM) TOTAL FROM T2
JOIN test_ShenLiang2025 T1
ON T2.STARTDATE>=T1.STARTDATE AND T2.ENDDATE<=T1.ENDDATE
GROUP BY T2.STARTDATE,T2.ENDDATE
ORDER BY T2.STARTDATE-- Step4 查看结果
/*
STARTDATE   ENDDATE     NUM
2021-04-20  2021-04-30  200
2021-05-01  2021-05-03  300
2021-05-04  2021-05-24  100
*/-- 注,注释记录过滤后结果见下图:

执行结果

时间序列错位还原之SQL实现案例详解相关推荐

  1. SQL IDENTITY_INSERT作用案例详解

    文章来源: 学习通http://www.jaxp.net/ 一般情况下,当数据表中,莫一列被设置成了标识列之后,是无法向标识列中手动的去插入标识列的显示值.但是,可以通过设置SET IDENTITY_ ...

  2. MySQL系列---架构与SQL执行流程详解

    文章目录 1. 背景 2. 架构体系 2.1 架构图 2.2 模块详解 2.3 架构分层 3. 查询SQL语句执行流程 3.1 连接 3.1.1 MySQL支持的通信协议 3.1.2 通信方式 3.2 ...

  3. html css主题,HTML+CSS=无限可能——案例详解:我的POI主题作品

    原标题:HTML+CSS=无限可能--案例详解:我的POI主题作品 在微博发了这个作业,收到很多好评,实在太开心! 斌叔让我来投稿,那今天就以这个网页为案例,把制作过程中我的方法和经验分享给大家. 作 ...

  4. wow mysql dbc_DBC中悲观锁介绍附案例详解

    DBC中悲观锁介绍附案例详解 了解下DBC中悲观锁: 代码如下: BDUtils 工具类: package JDBC; import java.sql.*; public class BDUtils ...

  5. 技术+案例详解无监督学习Autoencoder

    摘要:本篇文章将分享无监督学习Autoencoder的原理知识,然后用MNIST手写数字案例进行对比实验及聚类分析. 本文分享自华为云社区<[Python人工智能] 十五.无监督学习Autoen ...

  6. go mongodb排序查询_Kotlin与MongoDB整合CURD案例详解

    1.mongodb的低版本bson无法转换类型 比如MongoDB数据库表的字段类型为Decimal,实体类用String去定义就会报如下错误 No converter found capablof ...

  7. 【java学习之路】(java框架)004.Mybatis SQL映射文件详解

    02Mybatis SQL映射文件详解 ​ 在之前我们学习了mybatis的全局配置文件,下面我们开始学习mybatis的映射文件,在映射文件中,可以编写以下的顶级元素标签: cache – 该命名空 ...

  8. 数据湖架构Hudi(五)Hudi集成Flink案例详解

    五.Hudi集成Flink案例详解 5.1 hudi集成flink flink的下载地址: https://archive.apache.org/dist/flink/ Hudi Supported ...

  9. oracle rac 环境配置文件,学习笔记:Oracle RAC spfile参数文件配置案例详解

    天萃荷净 rac中的spfile探讨,记录一下Oracle RAC搭建完成后关于spfile参数文件的配置案例,与更改RAC环境中参数文件的方法 今天朋友的的rac,因为被同事做数据库升级,分别在两个 ...

最新文章

  1. JavaScript中常用的BOM属性
  2. 淘宝网的技术发展史(二) ——Oracle替换MySQL
  3. Node.js 多版本安装配置(Window、Ubuntu 、CentOS 、Mac OS、Cloud Studio)
  4. 采用递归求第n位数【C#】
  5. java struts2下载文件_java struts2入门学习---文件下载的二种方式
  6. redis rdb aof区别_Redis的持久化机制:RDB和AOF
  7. 2021.01.04
  8. 华为新机Mate30参数解析,这些参数你都知道是什么意思吗?
  9. solidworks2013安装
  10. 【深度】美俄机器人集群军事作战应用研究现状!三大关键技术体系分析
  11. 网站根目录与服务器根目录,根目录在哪里_网站的根目录在哪?急急!!!
  12. rust货轮什么时候出现_中国最早的汉字出现于什么时候?
  13. 杭电计算机组成原理实验RISC-V 实验 取指令及指令译码实验
  14. FinClip如何将H5工程转为小程序
  15. android keystore 查看、修改密码和别名等
  16. Isomorphic 同构树(图)的实现
  17. C语言 —— 函数(一)
  18. 如何在A4纸上打印标签
  19. word2vec(2) 背景知识
  20. NOIP 2018 游记

热门文章

  1. wxWidgets:wxComboCtrl 示例
  2. wxWidgets:wxFileDirPickerEvent类用法
  3. wxWidgets:wxDateTime类用法
  4. boost::python::converter::arg_to_python相关的测试程序
  5. boost::multi_array模块实现在矩阵上测试切片
  6. boost::hana::capture用法的测试程序
  7. boost::hana::common用法的测试程序
  8. GDCM:获取图像像素间距的测试程序
  9. GDCM:gdcm::VL 的测试程序
  10. VTK:Snippets之SaveSceneToFile