暂无图片
暂无图片
2
暂无图片
暂无图片
暂无图片

SQL经典案例之不同数据库的日期算术运算

原创 锁钥 2024-12-22
336

SQL经典案例之不同数据库日期算术运算的小区别

构造测试数据

-- postgresql/mysql drop table t_date_time; create table t_date_time(tid int,tdate date,ttime time,ttstamp timestamp); insert into t_date_time values(1,current_timestamp,current_timestamp,current_timestamp); insert into t_date_time values(2,'2025-01-01','09:00:00','2025-01-01 09:00:00'); insert into t_date_time values(3,'2025-01-28','13:14:56','2025-01-28 13:14:56'); insert into t_date_time values(4,'2025-02-04','04:03:01','2025-02-04 04:03:01'); insert into t_date_time values(5,'2025-04-04','14:04:50','2025-04-04 14:04:50'); insert into t_date_time values(6,'2025-04-05','15:05:50','2025-04-05 15:05:50'); insert into t_date_time values(7,'2025-04-06','16:04:50','2025-04-06 16:04:50'); insert into t_date_time values(8,'2025-05-31','13:31:33','2025-05-31 13:31:33'); insert into t_date_time values(9,'2025-06-02','06:06:06','2025-06-02 06:06:06'); insert into t_date_time values(10,'2025-10-01','10:10:10','2025-10-01 10:10:10'); -- oracle alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss'; alter session set nls_timestamp_format='YYYY-MM-DD HH24:MI:SS:FF6'; col ttstamp format a30 drop table t_date_time; create table t_date_time(tid int,tdate date,ttstamp timestamp); insert into t_date_time values(1,current_timestamp,current_timestamp); insert into t_date_time values(2,'2025-01-01 09:00:00','2025-01-01 09:00:00'); insert into t_date_time values(3,'2025-01-28 13:14:56','2025-01-28 13:14:56'); insert into t_date_time values(4,'2025-02-04 04:03:01','2025-02-04 04:03:01'); insert into t_date_time values(5,'2025-04-04 14:04:50','2025-04-04 14:04:50'); insert into t_date_time values(6,'2025-04-05 15:05:50','2025-04-05 15:05:50'); insert into t_date_time values(7,'2025-04-06 16:04:50','2025-04-06 16:04:50'); insert into t_date_time values(8,'2025-05-31 13:31:33','2025-05-31 13:31:33'); insert into t_date_time values(9,'2025-06-02 06:06:06','2025-06-02 06:06:06'); insert into t_date_time values(10,'2025-10-01 10:10:10','2025-10-01 10:10:10'); insert into t_date_time values(11,sysdate,sysdate); commit; select * from t_date_time;

日期类型

  • pg和mysql的date类型都是年月日,oracle则是年月日时分秒
  • oracle的sysdate为是年月日时分秒,而current_timestamp则带小数秒和时区
  • pg 的timestamp类型默认不带时区,可以使用without/with time zone 来指定是否带时区

image.png

加减日期时间

Oracle

  • 可用加减法运算来加减天数
  • 年月可用add_months函数
  • 对timestamp类型建议使用 INTERVAL 方式做运算,不然会丢失小数秒位的精度
select tid,ttstamp, ttstamp + interval '5' second as tsp_plus_5S, ttstamp + interval '5' minute as tsp_plus_5MI, ttstamp + interval '5' hour as tsp_plus_5H, ttstamp - 5 as tsp_minus_5D, add_months(ttstamp,-5) as tps_minus_5M, add_months(ttstamp,5*12) as tps_plus_5Y from t_date_time where rownum<3;

image.png

MySQL

  • 用关键字 INTERVAL 指定单位和数量
  • 也可使用 DATE_ADD 函数
select tid,ttstamp, ttstamp - interval 5 second as tps_minus_5S, ttstamp - interval 5 minute as tps_minus_5MI, ttstamp - interval 5 hour as tps_minus_5H, ttstamp - interval 5 day as tsp_minus_5D, ttstamp - interval 5 month as tps_minus_5M, ttstamp + interval 5 year as tps_plus_5Y, date_add(ttstamp,interval -5 day) as tsp_add_minus_5D, date_add(ttstamp,interval -5 month) as tsp_add_minus_5M, date_add(ttstamp,interval 5 year) as tsp_add_plus_5Y from t_date_time limit 2\G

image.png

PostgreSQL

  • 用关键字 INTERVAL 指定单位和数量且需放在单引号内
  • 注意秒和分钟的关键字结尾是带 s
select tid,ttstamp, ttstamp + interval '5 seconds' as tsp_plus_5S, ttstamp + interval '5 minutes' as tsp_plus_5MI, ttstamp + interval '5 hour' as tsp_plus_5H, ttstamp - interval '5 day' as tsp_minus_5D, ttstamp - interval '5 month' as tps_minus_5M, ttstamp + interval '5 year' as tps_plus_5Y from t_date_time limit 2;

image.png

两个日期相差的天数

-- postgresql/oracle select tsp_2,tsp_3,tsp_3 - tsp_2 from ( select ttstamp as tsp_2 from t_date_time where tid = 2) x, (select ttstamp as tsp_3 from t_date_time where tid = 3) y; -- mysql select tsp_2,tsp_3,datediff(tsp_3,tsp_2) from ( select ttstamp as tsp_2 from t_date_time where tid = 2) x, (select ttstamp as tsp_3 from t_date_time where tid = 3) y;

image.png

MySQL的DATEDIFF(end_date, start_date)函数,返回一个整数,可以为负数

  • end_date:表示要计算的时间段的结束日期
  • start_date:表示要计算的时间段的开始日期

两个日期相差的月/年数

找出两个日期相隔的月份,再除以12即相隔多少年

MONTHS_BETWEEN

Oracle使用months_between函数确定两个日期相隔的月数,日期相同返回 0

select tsp_2,tsp_9,months_between(tsp_9,tsp_2) as btmn,months_between(tsp_9,tsp_2)/12 as btyear from ( select ttstamp as tsp_2 from t_date_time where tid = 2) x, (select ttstamp as tsp_9 from t_date_time where tid = 9) y;

image.png
2025-06-02 06:00:00 与 2025-01-01 09:00:00 相差5个月加(24-9+6)小时,除以24转成天,再按月换算成小数(在oracle里面,以31天为基数):
image.png

YEAR/MONTH

MySQL使用函数 YEAR 和 MONTH 返回指定日期的4位年份和2位月份

select tsp_2,tsp_9,year(tsp_9),year(tsp_2),month(tsp_9),month(tsp_2), (year(tsp_9) - year(tsp_2))*12 + (month(tsp_9) - month(tsp_2)) as btmn, (year(tsp_9) - year(tsp_2))*12 + (month(tsp_9) - month(tsp_2))/12 as btyear from ( select ttstamp as tsp_2 from t_date_time where tid = 2) x, (select ttstamp as tsp_9 from t_date_time where tid = 9) y;

image.png

EXTRACT

PostgreSQL使用 EXTRACT 函数返回指定日期的4位年份和2位月份,该函数用于从一个日期或时间型的字段内抽取年、月、日、时、分、秒数据,支持关健字 YEAR、MONTH、DAY、HOUR、MINUTE、SECOND、WEEKDAY、YEARDAY

EXTRACT(关健字 FROM 日期或时间型字段)

select tsp_2,tsp_9,extract(year from tsp_9),extract(year from tsp_2),extract(month from tsp_9),extract(month from tsp_2), (extract(year from tsp_9) - extract(year from tsp_2))*12 + (extract(month from tsp_9) - extract(month from tsp_2)) as btmn, ((extract(year from tsp_9) - extract(year from tsp_2))*12 + (extract(month from tsp_9) - extract(month from tsp_2)))/12 as btyear from ( select ttstamp as tsp_2 from t_date_time where tid = 2) x, (select ttstamp as tsp_9 from t_date_time where tid = 9) y;

image.png

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论