You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用Hive或SQL获取日期所在季度及前两季度的首尾日期

如何用Hive/SQL获取指定日期的季度首尾日及往前推两个季度的首尾日

针对你提出的需求,我会分别给出Hive和SQL(以MySQL兼容写法为例)的实现方案,同时结合你提供的2014-02-03示例来验证效果。


一、获取指定日期所在季度的首日与末日

1. Hive实现

Hive自带的日期函数能快速处理这类需求:

  • 季度首日:用trunc()函数,第二个参数传'Q'可直接截断到当前季度第一天
    SELECT trunc('2014-02-03', 'Q') AS quarter_start;
    -- 输出:2014-01-01
    
  • 季度末日:先通过trunc()拿到季度首日,再加2个月得到季度最后一个月,最后用last_day()取该月最后一天
    SELECT last_day(add_months(trunc('2014-02-03', 'Q'), 2)) AS quarter_end;
    -- 输出:2014-03-31
    

2. SQL实现(MySQL为例)

MySQL没有直接的季度截断函数,但可以通过日期拼接计算实现:

  • 季度首日:提取年份后,计算当前季度的第一个月份,再拼接成标准日期
    SELECT STR_TO_DATE(
      CONCAT(YEAR('2014-02-03'), '-', FLOOR((MONTH('2014-02-03')-1)/3)*3 + 1, '-01'),
      '%Y-%m-%d'
    ) AS quarter_start;
    -- 输出:2014-01-01
    
  • 季度末日:先拿到季度首日,再加2个月后取该月最后一天
    SELECT LAST_DAY(
      DATE_ADD(
        STR_TO_DATE(CONCAT(YEAR('2014-02-03'), '-', FLOOR((MONTH('2014-02-03')-1)/3)*3 +1, '-01'), '%Y-%m-%d'),
        INTERVAL 2 MONTH
      )
    ) AS quarter_end;
    -- 输出:2014-03-31
    

二、获取指定日期往前推两个季度的首日与末日

核心思路是先将日期往前偏移6个月,再按上面的方法计算偏移后日期所在季度的首尾日。这里要纠正个小细节:9月没有31日,你示例里的2013年9月31日应该是2013年9月30日哦。

1. Hive实现

  • 往前推两季度的首日:用add_months()减6个月,再用trunc()截断到季度首
    SELECT trunc(add_months('2014-02-03', -6), 'Q') AS two_q_ago_start;
    -- 输出:2013-07-01
    
  • 往前推两季度的末日:基于上面的首日,加2个月后取最后一天
    SELECT last_day(add_months(trunc(add_months('2014-02-03', -6), 'Q'), 2)) AS two_q_ago_end;
    -- 输出:2013-09-30
    

2. SQL实现(MySQL为例)

  • 往前推两季度的首日:先将日期减6个月,再计算该日期所在季度的首日
    SELECT STR_TO_DATE(
      CONCAT(
        YEAR(DATE_SUB('2014-02-03', INTERVAL 6 MONTH)),
        '-',
        FLOOR((MONTH(DATE_SUB('2014-02-03', INTERVAL 6 MONTH))-1)/3)*3 +1,
        '-01'
      ),
      '%Y-%m-%d'
    ) AS two_q_ago_start;
    -- 输出:2013-07-01
    
  • 往前推两季度的末日:基于偏移后的季度首日,加2个月取最后一天
    SELECT LAST_DAY(
      DATE_ADD(
        STR_TO_DATE(
          CONCAT(
            YEAR(DATE_SUB('2014-02-03', INTERVAL 6 MONTH)),
            '-',
            FLOOR((MONTH(DATE_SUB('2014-02-03', INTERVAL 6 MONTH))-1)/3)*3 +1,
            '-01'
          ),
          '%Y-%m-%d'
        ),
        INTERVAL 2 MONTH
      )
    ) AS two_q_ago_end;
    -- 输出:2013-09-30
    

补充个小提示:如果是PostgreSQL这类数据库,逻辑会更简洁——用DATE_TRUNC('quarter', '2014-02-03'::date)直接拿季度首日,末日则是DATE_TRUNC('quarter', '2014-02-03'::date) + INTERVAL '3 months' - INTERVAL '1 day'

内容的提问来源于stack exchange,提问作者sahboor

火山引擎 最新活动