• Postgresql中,计算两个日期月份差值,实现ORACLE中MONTHS_BETWEEN的效果


    Oracle中存在months_between、add_months函数,用作计算年龄等,例如计算某个人的年龄:岁(age)-月(monthss)-天(days)

    SELECT rowid,
           a.fidate,
           a.fbirth,
           trunc(months_between(fidate, fbirth) / 12) age,
           trunc(mod(months_between(fidate, fbirth), 12)) monthss,
           trunc(fidate -
                 add_months(fbirth, trunc(months_between(fidate, fbirth)))) days
      from t_noentryquery a;
    

    Oracle中调用,如下图:
    在这里插入图片描述

    为兼容Postgresql计算年龄等,以此来创建函数months_between

    --入参为date类型
    CREATE OR REPLACE FUNCTION months_between(date1 date, date2 date)
    RETURNS "pg_catalog"."int4" AS $BODY$
    DECLARE
    v_res int;
    begin
    SELECT 12*EXTRACT(YEAR from age(date1,  date2))+EXTRACT(MONTH from age(date1, date2)) into v_res from dual;
    RETURN v_res;
    end;
    $BODY$
    LANGUAGE plpgsql VOLATILE
    COST 100;
    
    --或者
    
    --入参为 timestamp without time zone类型
    CREATE OR REPLACE FUNCTION months_between(
    	date1 timestamp without time zone,
    	date2 timestamp without time zone)
        RETURNS integer
        LANGUAGE 'plpgsql'
        COST 100
        VOLATILE PARALLEL UNSAFE
    AS $BODY$
    DECLARE
    v_res int;
    begin
    SELECT 12*EXTRACT(YEAR from age(date1::date,  date2::date))+EXTRACT(MONTH from age(date1::date, date2::date)) into v_res from dual;
    RETURN v_res;
    end;
    $BODY$;
    

    为兼容Postgresql计算年龄等,以此来创建函数add_months

    --入参为timestamp without time zone,numeric类型
    create or replace function add_months(timestamp without time zone, numeric) returns timestamp as $$  
    declare  
      i interval := ($2 || 'month');  
      d1 date := date(to_timestamp($1::text,'yyyy-mm') + interval '1 month' - interval '1 day');  
      d2 date := date($1);  
      res timestamp;  
    begin  
      select case when d1=d2 then ((to_char($1+i+interval '1 month', 'yyyy-mm')||'-01')::date - 1) + $1::time else $1+i end into res;  
      return res;  
    end;  
    $$ language plpgsql strict; 
    
    --或者
    
    --入参为timestamp,numeric类型
    create or replace function add_months(timestamp, numeric) returns timestamp as $$  
    declare  
      i interval := ($2 || 'month');  
      d1 date := date(to_timestamp($1::text,'yyyy-mm') + interval '1 month' - interval '1 day');  
      d2 date := date($1);  
      res timestamp;  
    begin  
      select case when d1=d2 then ((to_char($1+i+interval '1 month', 'yyyy-mm')||'-01')::date - 1) + $1::time else $1+i end into res;  
      return res;  
    end;  
    $$ language plpgsql strict; 
    
    

    Postgresql中调用:

    SELECT 
           a.fidate,
           a.fbirth,
           trunc(months_between(fidate, fbirth) / 12) age,
           trunc(mod(months_between(fidate, fbirth), 12)) monthss,
           trunc(fidate::date - add_months(fbirth,
             cast(trunc(months_between(fidate, fbirth)) as numeric))::date) days
      from t_noentryquery a;
    
    

    如下图:
    在这里插入图片描述

    当然也可以用Postgresql中自带的函数age(),更加方便快捷

    select age(fidate ::date, fbirth ::date), a.fidate, a.fbirth
      from T_NOENTRYQUERY a
     where a.fidate is not null
       and a.fbirth is not null
    

    如下图:
    在这里插入图片描述

  • 相关阅读:
    Windows 10 读取bitlocker加密的硬盘出现参数错误怎么解决?
    Netty从入门到实战
    自动驾驶行业数据防泄漏解决方案分享
    openlayers点线面测量、绘制设计实现
    回归预测 | MATLAB实现PSO-SVR粒子群优化支持向量机回归多输入单输出预测
    MySQL备份与恢复
    常见面试题:js篇
    阿里巴巴最新的 SpringCloud 面试题是如何让我“颜面扫地”的?
    Java手写红黑树应用拓展案例
    有没有友友会make或n8n啊
  • 原文地址:https://blog.csdn.net/weixin_42064877/article/details/127104044