达梦(DM) SQL日期操作及分析函数

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云原生数据库 PolarDB 分布式版,标准版 2核8GB
简介: 讲述DM 数据库中如何实现各种日期相关的运算以及如何利用分析函数 lead() over() 进行范围问题的处理

本文主要讲述DM 数据库中如何实现各种日期相关的运算以及如何利用分析函数 lead() over() 进行范围问题的处理。

日期操作

SYSDATE

使用 trunc() 函数获得某个日期对应的月初时间

SELECT ename,hiredate AS 入职日期,TRUNC (hiredate,'mm')AS 月初 FROM employee WHERE ROWNUM <=1;

image.png

获取具体时间的时分秒、年月日、月初、周初、年初等

SELECT hiredate,       TO_NUMBER (TO_CHAR (hiredate,'hh24')),       TO_NUMBER (TO_CHAR (hiredate,'mi')),       TO_NUMBER (TO_CHAR (hiredate,'ss')),       TO_NUMBER (TO_CHAR (hiredate,'dd')),       TO_NUMBER (TO_CHAR (hiredate,'mm')),       TO_NUMBER (TO_CHAR (hiredate,'yyyy')),       TO_NUMBER (TO_CHAR (hiredate,'ddd')) 年内第几天,       TRUNC (hiredate,'dd') 一天之始,       TRUNC (hiredate,'day') 周初,       TRUNC (hiredate,'mm') 月初,       LAST_DAY (hiredate) 月末,       ADD_MONTHS (TRUNC (hiredate,'mm'),1) 下月初,       TRUNC (hiredate,'yy') 年初,       TO_CHAR (hiredate,'day') 周几,       TO_CHAR (hiredate,'month') 月份
FROM(SELECT hiredate FROM employee
WHERE ROWNUM <=1);

image.png

EXTRACT

EXTRACT 函数可以提取时间字段中的年、月、日、时、分、秒,返回的值为 NUMBER 类型

SELECT EXTRACT (YEARFROM SYSTIMESTAMP)AS,       EXTRACT (MONTH FROM SYSTIMESTAMP)AS,       EXTRACT (DAY FROM SYSTIMESTAMP)AS,       EXTRACT (HOUR FROM SYSTIMESTAMP)AS,       EXTRACT (MINUTE FROM SYSTIMESTAMP)AS,       EXTRACT (SECOND FROM SYSTIMESTAMP)ASFROM DUAL;

image.png

to_char 函数可以用来取日期时间类型字段中的时、分、秒

SELECT hiredate, TO_CHAR (hiredate,'dd')AS, TO_CHAR (hiredate,'hh24')ASFROM employee WHERE ROWNUM <=1;

image.png

EXTRACT 函数可以用来取 INTERVAL 中的信息,to_char 函数不支持

SELECT EXTRACT (HOUR FROM it)AS"hour"FROM(SELECT INTERVAL '2 12:30:59' DAY TO SECOND AS it FROM DUAL);

image.png

换成to_char函数

SELECT to_char(it,'hh24')AS"hour"FROM(SELECT INTERVAL '2 12:30:59' DAY TO SECOND AS it FROM DUAL);

image.png

判断一年是否为闰年

判断一年是否为闰年,可以看二月的月末具体是哪一天。使用 TO_CHAR、 LAST_DAY、 ADD_MONTHS、 TRUNC 函数共同实现

--计算年初  2023-01-01SELECT TRUNC (hiredate,'y') 年初 FROM employee WHERE ROWNUM <=1;--计算二月初 2023-02-01SELECT ADD_MONTHS (TRUNC (hiredate,'y'),1) 二月初 FROM employee WHERE ROWNUM <=1;--计算二月底  2023-02-28SELECT LAST_DAY (ADD_MONTHS (TRUNC (hiredate,'y'),1))AS 二月底 FROM employee WHERE ROWNUM <=1;--计算二月底对应的日期SELECT TO_CHAR (LAST_DAY (ADD_MONTHS (TRUNC (hiredate,'y'),1)),'DD')ASFROM employee WHERE ROWNUM <=1;

image.png

周的计算

使用 TO_CHAR、 NEXT_DAY、TRUNC 函数共同实现周的计算

WITH x
AS(SELECT TRUNC (SYSDATE,'yy')+(LEVEL -1)AS 日期 FROM DUAL CONNECT BY LEVEL <=8)SELECT 日期,       TO_CHAR (日期,'d')AS d,       TO_CHAR (日期,'day')AS day,       NEXT_DAY (日期,1)AS 下个周日,       TO_CHAR (日期,'ww')AS ww,       TO_CHAR (日期,'iw')AS iw
FROM x;

image.png

参数 “day” 与字符集无关,所以建议使用 “d”, WW 与 IW 都是取 “第几周”,只是两个参数的初始值不一样。

确定某月内第一个和最后一个周末某天的日期

返回当月内第一个星期一与最后一个星期一,我们分别找上月末及当月末之前七天的下一周的周一即可

SELECT NEXT_DAY (TRUNC (hiredate,'mm')-1,2) 第一个周一,       NEXT_DAY (LAST_DAY (TRUNC (hiredate,'mm'))-7,2) 最后一个周一
FROM employee
WHERE ROWNUM <=1;

image.png

确定指定年份季度的开始日期和结束日期

在写报表查询语句时需要按季度分类汇总,提取对应的季度开始日期和结束日期。可以通过 add_months、to_date 函数实现

SELECT sn AS 季度,(sn -1)*3+1AS 开始月份, ADD_MONTHS (TO_DATE (,'yyyy'),(sn -1)*3)AS 开始日期, ADD_MONTHS (TO_DATE (,'yyyy'), sn *3)-1AS 结束日期
FROM(SELECT'2023'AS, LEVEL AS sn FROM DUAL CONNECT BY LEVEL <=4);

image.png

补充范围内丢失的值

统计每一年份入职员工数,若表中没有的年份,则展示的统计人数为 0

WITH x
AS(SELECT 开始年份 +(LEVEL -1)AS 年份
FROM(SELECT EXTRACT (YEARFROM MIN (hiredate))AS 开始年份,                            EXTRACT (YEARFROM MAX (hiredate))AS 结束年份
FROM employee)         CONNECT BY LEVEL <= 结束年份 - 开始年份 +1)SELECT*FROM x;

image.png

关联查询得到结果集

WITH x
AS(SELECT 开始年份 +(LEVEL -1)AS 年份
FROM(SELECT EXTRACT (YEARFROM MIN (hiredate))AS 开始年份,                            EXTRACT (YEARFROM MAX (hiredate))AS 结束年份
FROM employee)         CONNECT BY LEVEL <= 结束年份 - 开始年份 +1)SELECT x.年份,COUNT(e.empno) 入职人数
FROM x
         LEFT JOIN employee e
ON(EXTRACT (YEARFROM e.hiredate)= x.年份)GROUPBY x.年份
ORDERBY1;

image.png

按照给定的时间单位查找

使用 to_char 函数查询给定时间单位的时间,比如查询如入职日期在 1 月或者 11 月且非星期三的员工信息

SELECT ename 姓名,       hiredate 入职日期,       TO_CHAR (hiredate,'day')AS 星期
FROM employee
WHERE TO_CHAR (hiredate,'mm')IN('01','11')AND TO_CHAR (hiredate,'d')!='4';

image.png

使用日期的特殊部分比较记录

使用 to_char 函数统计相同月份与周内日期入职的员工

SELECT ename 姓名,       hiredate 入职日期,       TO_CHAR (hiredate,'MON day')AS 月周
FROM(SELECT ename, hiredate,COUNT(*) OVER (PARTITION BY TO_CHAR (hiredate,'MON day'))AS ct
FROM employee)WHERE hiredate LIKE'2023%';

image.png

范围处理

分析函数

lead(列名,n,m) over(partition by ... order by ...),不带参数 n,m,则查找当前记录后面第一行的记录列名的值,参数说明

lead() 只能用于取后面第 n 行记录说明,不能取前面的。如果要取前面第 n 行记录说明,使用 lag()函数。
over() 在什么条件之上,使用语法 over(partition by...order by...)。
partition by 按某个字段划分组。
order by 按某个字段排序。

定位连续值的范围

可以使用分析函数 lead() over() 定位某一段连续值的范围

CREATEOR REPLACE VIEW v(pro_id,pro_start,pro_end)asSELECT1,date '2020-10-01',date '2020-10-02'FROM dual UNION ALL
SELECT2,date '2020-10-02',date '2020-10-03'FROM dual UNION ALL
SELECT3,date '2020-10-03',date '2020-10-06'FROM dual UNION ALL
SELECT4,date '2020-10-06',date '2020-10-07'FROM dual UNION ALL
SELECT5,date '2020-10-09',date '2020-10-11'FROM dual UNION ALL
SELECT6,date '2020-10-13',date '2020-10-15'FROM dual;SELECT*FROM v;

查看创建的视图v

image.png

现在需要查询连续值记录,即下一行记录的开始时间与上一行记录的结束时间一致

SELECT 工程号, 开始日期, 结束日期
FROM(SELECT pro_id AS 工程号,               pro_start AS 开始日期,               pro_end AS 结束日期,               LEAD (pro_start) OVER (ORDERBY pro_id) 下一工程开始日期
FROM v)WHERE 下一工程开始日期 = 结束日期;

image.png

查找同一分区中行之间的差

可以使用分析函数 lead() over() 查找同一分区中行之间的差

CREATEOR REPLACE VIEW v(log_name,log_time)asSELECT'HR',datetime'2020-10-01 09:28:00'FROM dual UNION ALL
SELECT'HR',datetime'2020-10-01 09:38:10'FROM dual UNION ALL
SELECT'HR',datetime'2020-10-01 10:50:00'FROM dual UNION ALL
SELECT'HR',datetime'2020-10-01 11:08:50'FROM dual UNION ALL
SELECT'SYSTEM',datetime'2020-10-01 09:18:00'FROM dual UNION ALL
SELECT'SYSTEM',datetime'2020-10-01 12:09:40'FROM dual;SELECT*FROM v;

创建视图v

image.png

现在需要各用户两次登录的时间间隔,首先使用分析函数 lead() over() 取出下一行信息

SELECT log_name AS 登录名,       log_time AS 登录时间,       LEAD (log_time) OVER (PARTITION BY log_name ORDERBY log_time) 下一登录时间
FROM v;

image.png

计算用户两次登录的时间间隔

SELECT log_name AS 登录名, log_time AS 登录时间,(next_log_time - log_time)*24*60AS 登录间隔
FROM(SELECT log_name, log_time, LEAD (log_time) OVER (PARTITION BY log_name ORDERBY log_time) next_log_time FROM v);

image.png

定位连续范围的起始点

创建视图v

CREATEOR REPLACE VIEW v(pro_id,pro_start,pro_end)asSELECT1,date '2020-10-01',date '2020-10-02'FROM dual UNION ALL
SELECT2,date '2020-10-02',date '2020-10-03'FROM dual UNION ALL
SELECT3,date '2020-10-03',date '2020-10-06'FROM dual UNION ALL
SELECT4,date '2020-10-06',date '2020-10-07'FROM dual UNION ALL
SELECT5,date '2020-10-09',date '2020-10-11'FROM dual UNION ALL
SELECT6,date '2020-10-13',date '2020-10-15'FROM dual;SELECT*FROM v;

image.png

要求把连续的项目合并,返回合并后的起始时间,首先提取上一个工程结束时间

CREATEOR REPLACE VIEW x0
ASSELECT pro_id AS 编号,          pro_start AS 开始日期,          pro_end AS 结束日期,          LAG (pro_end) OVER (ORDERBY pro_id)AS 上一工程结束日期
FROM v;SELECT*FROM x0;

image.png

标定项目的连续状态

CREATEOR REPLACE VIEW x1
ASSELECT 编号,          开始日期,          结束日期,          上一工程结束日期,          CASE WHEN 开始日期 = 上一工程结束日期 THEN 0 ELSE 1 END AS 连续状态 FROM x0;SELECT*FROM x1;

image.png

从结果图看出,每个连续分组的开始,都生成了一个“1”的标识,对位置状态进行累加,得到分组依据

CREATEOR REPLACE VIEW x2
ASSELECT 编号,          开始日期,          结束日期,          上一工程结束日期,          连续状态,          SUM(连续状态) over(ORDERBY 编号)AS 分组依据
FROM x1;SELECT*FROM x2;

image.png

通过提取数据、生成标识、累加标识这些操作后,得到了需要的 3 个连续分组

SELECT 分组依据,         MIN (开始日期)AS 开始日期,         MAX (结束日期)AS 结束日期
FROM x2
GROUPBY 分组依据
ORDERBY1;

image.png

到这里基于DM 数据库中如何实现各种日期相关的运算以及如何利用分析函数 lead() over() 进行范围问题的处理也就算说完了,下面继续进行后续的操作。

相关文章
|
5天前
|
SQL 数据库 数据安全/隐私保护
【操作宝典】SQL巨擘:掌握SQL Server Management的终极秘籍!
【操作宝典】SQL巨擘:掌握SQL Server Management的终极秘籍!
64 0
|
5天前
|
SQL 关系型数据库 分布式数据库
数据管理DMS操作报错合集之DMS SQL执行失败且无法看到原因,如何解决
数据管理DMS(Data Management Service)是阿里云提供的数据库管理和运维服务,它支持多种数据库类型,包括RDS、PolarDB、MongoDB等。在使用DMS进行数据库操作时,可能会遇到各种报错情况。以下是一些常见的DMS操作报错及其可能的原因与解决措施的合集。
|
5天前
|
SQL Oracle 关系型数据库
整合Mybatis-Plus高级,Oracle 主键Sequence,Sql 注入器实现自定义全局操作
整合Mybatis-Plus高级,Oracle 主键Sequence,Sql 注入器实现自定义全局操作
94 0
|
1天前
|
SQL Java 关系型数据库
实时计算 Flink版操作报错合集之通过flink sql形式同步数据到hudi中,本地启动mian方法报错如何解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
19 8
|
3天前
|
SQL 关系型数据库 MySQL
实时计算 Flink版产品使用合集之当 SQL Server 源数据库中的数据更新后,CDC 吐出的操作(op)是怎样的
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
14 0
|
5天前
|
SQL Java 数据库连接
【JavaEE】懒人的福音-MyBatis框架—复杂的操作-动态SQL(下)
【JavaEE】懒人的福音-MyBatis框架—复杂的操作-动态
6 0
|
5天前
|
SQL Java 数据库连接
【JavaEE】懒人的福音-MyBatis框架—复杂的操作-动态SQL(上)
【JavaEE】懒人的福音-MyBatis框架—复杂的操作-动态SQL
5 0
|
5天前
|
SQL JSON 分布式计算
实时数仓 Hologres产品使用合集之在执行SQL语句时,在插入语句后面直接跟上了insert,insert操作就会报错如何解决
实时数仓Hologres是阿里云推出的一款高性能、实时分析的数据库服务,专为大数据分析和复杂查询场景设计。使用Hologres,企业能够打破传统数据仓库的延迟瓶颈,实现数据到决策的无缝衔接,加速业务创新和响应速度。以下是Hologres产品的一些典型使用场景合集。
43 0
实时数仓 Hologres产品使用合集之在执行SQL语句时,在插入语句后面直接跟上了insert,insert操作就会报错如何解决
|
5天前
|
SQL 分布式计算 DataWorks
DataWorks操作报错合集之在DataWorks中使用ODPS SQL时遇到"该文件对应引擎实例已失效,请重新选择可用的引擎实例"的错误提示”,是什么导致的
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
40 0
|
5天前
|
SQL 分布式计算 大数据
MaxCompute操作报错合集之在sql 里嵌套查询时,查询条件带有instr时报错,如何解决
MaxCompute是阿里云提供的大规模离线数据处理服务,用于大数据分析、挖掘和报表生成等场景。在使用MaxCompute进行数据处理时,可能会遇到各种操作报错。以下是一些常见的MaxCompute操作报错及其可能的原因与解决措施的合集。
http://www.vxiaotou.com