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

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS SQL Server,基础系列 2核4GB
简介: 讲述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() 进行范围问题的处理也就算说完了,下面继续进行后续的操作。

相关文章
|
2月前
|
SQL
开发指南057-执行SQL返回结果集
业务实践中除了返回实体类外,经常需要通过SQL语句返回结果集
|
2月前
|
SQL 存储 数据可视化
手机短信SQL分析技巧与方法
在手机短信应用中,SQL分析扮演着至关重要的角色
|
2月前
|
SQL 开发框架 .NET
sql server日期时间函数
sql server日期时间函数
54 2
|
2月前
|
SQL 安全
开发指南038-防SQL注入
这个是检查某个字符串是否含注入的SQL,为基本函数
|
2月前
|
SQL 关系型数据库 MySQL
SQL日期函数
SQL日期函数
|
4月前
|
前端开发 Java JSON
Struts 2携手AngularJS与React:探索企业级后端与现代前端框架的完美融合之道
【8月更文挑战第31天】随着Web应用复杂性的提升,前端技术日新月异。AngularJS和React作为主流前端框架,凭借强大的数据绑定和组件化能力,显著提升了开发动态及交互式Web应用的效率。同时,Struts 2 以其出色的性能和丰富的功能,成为众多Java开发者构建企业级应用的首选后端框架。本文探讨了如何将 Struts 2 与 AngularJS 和 React 整合,以充分发挥前后端各自优势,构建更强大、灵活的 Web 应用。
65 0
|
4月前
|
Java 应用服务中间件 Maven
从零到英雄:一步步构建你的首个 JSF 应用程序,揭开 JavaServer Faces 的神秘面纱
【8月更文挑战第31天】JavaServer Faces (JSF) 是一种强大的 Java EE 标准,用于构建企业级 Web 应用。它提供了丰富的组件库和声明式页面描述语言 Facelets,便于开发者快速开发功能完善且易于维护的 Web 应用。本文将指导你从零开始构建一个简单的 JSF 应用,包括环境搭建、依赖配置、Managed Bean 编写及 Facelets 页面设计。
109 0
|
4月前
|
SQL 数据采集 数据挖掘
为什么要使用 SQL 函数?详尽分析
【8月更文挑战第31天】
63 0
|
4月前
|
SQL 关系型数据库 MySQL
【超全整理】SQL日期与时间函数大汇总会:MySQL与SQL Server双轨对比教学,助你轻松搞定时间数据处理难题!
【8月更文挑战第31天】本文介绍了在不同SQL数据库系统(如MySQL、SQL Server、Oracle)中常用的日期与时间函数,包括DATE、NOW()、EXTRACT()、DATE_ADD()、TIMESTAMPDIFF()及日期格式化等,并提供了具体示例。通过对比这些函数在各系统中的使用方法,帮助开发者更高效地处理日期时间数据,满足多种应用场景需求。
566 0
|
4月前
|
SQL 数据采集 算法
【电商数据分析利器】SQL实战项目大揭秘:手把手教你构建用户行为分析系统,从数据建模到精准营销的全方位指南!
【8月更文挑战第31天】随着电商行业的快速发展,用户行为分析的重要性日益凸显。本实战项目将指导你使用 SQL 构建电商平台用户行为分析系统,涵盖数据建模、采集、处理与分析等环节。文章详细介绍了数据库设计、测试数据插入及多种行为分析方法,如购买频次统计、商品销售排名、用户活跃时间段分析和留存率计算,帮助电商企业深入了解用户行为并优化业务策略。通过这些步骤,你将掌握利用 SQL 进行大数据分析的关键技术。
252 0