如何用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




