【SQL】SQL的日期与时间函数

【SQL】SQL的日期与时间函数

一、引言

今天来聊聊 Hive 里日期和时间函数的应用场景。

做数据分析的同学都知道,日期处理绝对是个"高频刚需"------无论是统计报表、用户行为分析,还是考勤打卡、业务指标计算,到处都要跟日期打交道。
Hive 提供了超级丰富的日期函数,用好了能省很多事儿。

今天咱们梳理下 Hive 里常用的日期时间函数系统梳理一遍,配上实战案例,保证你看完就能用上。


二、核心函数一览

先上一个表格,让大家对 Hive 日期函数有个全局印象:

函数类别 常用函数 说明
日期计算 date_add/date_sub, date_add/minus 日期加减
日期差值 datediff, months_between 计算日期间隔
日期提取 year/month/day/hour/minute/second 提取日期各部分
格式化 date_format, from_unixtime, unix_timestamp 日期与字符串互转
时间戳 unix_timestamp, from_unixtime 时间戳处理
其他 trunc, datetrunc,current_date, now 日期工具函数

三、常见案例枚举

1. 日期计算(加减、差值)

日期加减

sql 复制代码
-- 当前日期加减N天
SELECT
    current_date AS 今日,
    date_add(current_date, 7) AS 七天后,
    date_sub(current_date, 30) AS 三十天前;

划重点:date_adddate_sub 接受负数,效果反一反就对了。

sql 复制代码
-- 简单写法:直接用 + -  是不是很神奇~
SELECT
    current_date,
    current_date + 7,   -- 等同于 date_add
    current_date - 30;  -- 等同于 date_sub

计算日期间隔

sql 复制代码
-- 计算两个日期相差天数,这里需注意日期格式DATE、DATETIME或TIMESTAMP类型,不然会报错
SELECT
    datediff('2026-04-23', '2026-01-01') AS 天数差;

-- 计算月数差(返回小数)
SELECT
    months_between('2026-04-23', '2025-01-01') AS 月数差;

划重点:datediff 只计算日期部分,忽略时间;months_between 会精确到月。

如果用的是阿里云ODPS,SELECT DATEDIFF(TIMESTAMP '2006-01-01 00:00:00', TIMESTAMP '2005-12-31 23:59:59', 'dd') 后面可以限制日期部分为年月日、时分秒都行;

实战:计算用户最近N天活跃

sql 复制代码
-- 统计近7天有活跃的用户   是不是面试很熟悉?
SELECT  user_id,
        count(*) AS 活跃天数
FROM user_log
WHERE dt >= date_sub(current_date, 7)
GROUP BY user_id
HAVING count(*) >= 3;  -- 至少活跃3天才算

2. 格式化与解析

日期转字符串

sql 复制代码
-- date_format:灵活格式化
SELECT
    current_timestamp AS 当前时间,
    date_format(current_timestamp, 'yyyy-MM-dd') AS 日期,
    date_format(current_timestamp, 'yyyy-MM-dd HH:mm:ss') AS 完整时间,
    date_format(current_timestamp, 'yyyy年MM月dd日') AS 中文格式,
    date_format(current_timestamp, 'yyyyMMdd') AS 紧凑格式;

输出示例:

复制代码
当前时间                    | 日期        | 完整时间                | 中文格式       | 紧凑格式
2026-04-23 16:44:00        | 2026-04-23  | 2026-04-23 16:44:00     | 2026年04月23日 | 20260423

字符串转日期

sql 复制代码
-- 字符串转日期
SELECT
    to_date('2026-04-23 16:44:00') AS 日期部分,
    to_date('20260423') AS 字符串日期;

-- 指定格式解析
SELECT
    from_unixtime(unix_timestamp('23/04/2026', 'dd/MM/yyyy'), 'yyyy-MM-dd') AS 解析后;

划重点:字符串格式不统一时,用 unix_timestamp(str, format) 指定格式。


3. 日期提取

sql 复制代码
-- 提取年月日时分秒
SELECT
    current_timestamp             AS 时间,
    year(current_timestamp)       AS 年,
    month(current_timestamp)      AS 月,
    day(current_timestamp)        AS 日,
    hour(current_timestamp)       AS 时,
    minute(current_timestamp)     AS 分,
    second(current_timestamp)     AS 秒,
    dayofweek(current_timestamp)  AS 星期几,  -- 1=周日
    weekofyear(current_timestamp) AS 第几周;

截断到指定粒度

sql 复制代码
-- trunc:截断日期
SELECT
    current_date AS 今天,
    trunc(current_date, 'MM') AS 月初,     -- 截断到月
    trunc(current_date, 'YY') AS 年初,      -- 截断到年
    trunc(current_date, 'DD') AS 当天零点;  -- 截断到日

划重点:trunc 在Hive里支持 MM(月初)、YY(年初)、DD(日)等格式。


4. 时间戳处理

时间戳互转

sql 复制代码
-- 当前时间戳
SELECT
    unix_timestamp() AS 当前时间戳,
    from_unixtime(unix_timestamp()) AS 时间戳转字符串;

-- 指定时间转时间戳
SELECT
    unix_timestamp('2026-04-23 16:44:00') AS 指定时间的时间戳;

-- 时间戳转指定格式
SELECT
    from_unixtime(1713861840, 'yyyy-MM-dd HH:mm:ss') AS 转日期格式;

毫秒级时间戳

sql 复制代码
-- 毫秒级时间戳(13位)
SELECT
    unix_timestamp() * 1000 AS 毫秒时间戳;

-- 毫秒转日期
SELECT
    from_unixtime(1713861840000 / 1000) AS 毫秒转日期;

划重点:Hive 的 unix_timestamp 是秒级(10位),Java/JavaScript 是毫秒级(13位),注意换算。


5. 常见业务场景

场景一:考勤打卡统计

sql 复制代码
-- 统计每人每月上班天数
SELECT
    user_id,
    name,
    date_format(clock_time, 'yyyy-MM') AS 月份,
    count(DISTINCT date(clock_time)) AS 上班天数,
    sum(case when hour(clock_time) > 9 then 1 else 0 end) AS 迟到次数
FROM attendance
WHERE year(clock_time) = 2026
GROUP BY
    user_id,
    name,
    date_format(clock_time, 'yyyy-MM');

场景二:月报表统计

sql 复制代码
-- 计算每月的自然月周期
SELECT
    trunc(create_time, 'MM') AS 月份,
    count(*) AS 新增用户,
    sum(payment_amount) AS 成交金额
FROM order_log
WHERE create_time >= date_sub(trunc(current_date, 'MM'), 30)  -- 近30个自然月
GROUP BY trunc(create_time, 'MM')
ORDER BY 月份 DESC;

场景三:周环比分析

sql 复制代码
-- 本周 vs 上周 指标对比
WITH weekly_stats AS (
    SELECT
        date_format(dt, 'yyyy-iw') AS 周,
        sum(pv) AS 总PV,
        sum(uv) AS 总UV
    FROM page_stats
    WHERE dt >= date_sub(current_date, 56)  -- 预留8周
    GROUP BY date_format(dt, 'yyyy-iw')
)
SELECT
    w1.周 AS 本周,
    w1.总PV AS 本周PV,
    w0.周 AS 上周,
    w0.总PV AS 上周PV,
    round((w1.总PV - w0.总PV) * 100.0 / w0.总PV, 2) AS 环比增幅百分比
FROM weekly_stats w1
LEFT JOIN weekly_stats w0
ON        datediff(to_date(concat(substr(w1.周, 6), '-1')), to_date(concat(substr(w0.周, 6), '-1'))) = 7
WHERE w1.周 = date_format(current_date, 'yyyy-iw');

四、总结对比

场景 推荐函数
日期加减 date_add / date_sub+/-
计算差值 datediff/ months_between
提取部分 year month day hour
日期格式化 date_format(from, to)
字符串转日期 to_date / unix_timestamp(str, format)
时间戳互转 unix_timestamp / from_unixtime
日期截断 trunc(date, unit)

最后给个小建议:日常写 SQL 时,能用 日期函数 就不用字符串拼接,日期函数比字符串拼接解析稳定且高效,而且跨版本兼容性更好。

好了,今天的分享就到这里,觉得有用动动小手点赞+关注+收藏,一键三连~ 有问题留言沟通啦~

相关推荐
步辞2 小时前
JavaScript中Symbol-keyFor检索全局符号键名逻辑
jvm·数据库·python
瀚高PG实验室2 小时前
磁盘故障导致数据库进入恢复模式
数据库·瀚高数据库
看海的四叔2 小时前
【SQL】SQL-常见窗口函数有哪些-上篇
数据库·hive·sql·mysql·数据分析·窗口函数
pele2 小时前
如何处理ORA-01152报错_恢复未完成导致的数据文件仍需介质恢复
jvm·数据库·python
IntMainJhy2 小时前
【flutter for open harmony】Flutter SQLite 本地数据库的鸿蒙化适配与实战指南
数据库·flutter·sqlite
qq_372154232 小时前
SQL如何避免隐式类型转换导致的慢查询_参数类型对齐与索引失效
jvm·数据库·python
qq_342295822 小时前
MySQL怎样在触发器中引用新旧数据行_NEW与OLD关键字详解
jvm·数据库·python
m0_746752302 小时前
如何配置Data Guard主备库目录结构不同_DB_FILE_NAME_CONVERT参数转换规则
jvm·数据库·python
weixin_424999362 小时前
CSS如何解决CSS冲突导致的BUG_使用CSS层叠层特性隔离样式
jvm·数据库·python