hive sql中传date 指定后的“%Y-%m-%d“格式,需要加引号

本文探讨了在Hive环境中优化SQL查询的方法,通过具体案例展示了如何调整查询语句以提高查询效率,尤其是在处理大数据集时。文章对比了不同查询语句的执行效果,强调了正确使用日期格式和字符串传递的重要性。

其中dt_playtime在shell中的变量赋值为dt_playtime=`date -d "$dt" +"%Y-%m-%d"` ##需要传递为字符串,加引号才能被识别

## 先查苏打播放器的时间
原语句为:
SELECT
      did,uuid,
      if( cast(duration as float) is NULL, 0.0, cast(duration as float) ) as duration
      FROM
          mds_suda_video_playtime_hour  -- 这边日志表,是播放器的日志表,“小时级别的播放器日志表”,一小时一个日志,按小时分区存的
     WHERE dt='${hiveconf:dt_playtime}'
改写为
hive -e "SELECT suda_inter.did,
      suda_inter.uuid,
      max(suda_inter.duration) as suda_durseconds
      FROM(
        SELECT
          did,uuid,
          if( cast(duration as float) is NULL, 0.0, cast(duration as float) ) as duration
          FROM
              mds_suda_video_playtime_hour
         WHERE dt='2020-07-16') suda_inter
     GROUP BY suda_inter.did,suda_inter.uuid
     limit 100;"
## 这上面的dt必须要加引号才能有结果。其中dt_playtime在shell中的变量赋值为dt_playtime=`date -d "$dt" +"%Y-%m-%d"`
##需要传递为字符串才能被识别
#f2817e2796dbf018        ef6814f2a063378aa020cfa6fb3e66e3        11.0
#e1d82800867fca03        fcefd08cd9083c43a7822a7a2cd169e2        6.0
#3ef38f5a2d17f708        8e1112b61d3e35fe9a977071c65400e6        37.0

## 再查apache播放器的时间
## 原语句为:

SELECT
  device_id,uuid,req_id,
  collect_set(play_duration)      as play_duration, -- 播放时长
  FROM
      mds_apache_code_v3  -- web的后台日志表,web 端的所有行为数据日志都有,
 WHERE dt='${hiveconf:dt}'
 GROUP BY device_id,uuid,req_id,timestamp
 --上面的dt传时间格式为20200716,可加引号可不加

hive -e "SELECT
      device_id,uuid,
      collect_set(play_duration)      as play_duration
      FROM mds_apache_code_v3
     WHERE dt=20200716
     GROUP BY device_id,uuid,req_id,timestamp
     limit 100"

#上面的dt 是没有加引号的,但是有结果
#结果: 是有非空时长的,即apache这的duration 是有播放时长的
#000168c99f29f3b5        60920638655b3ff6b5c3103741081a97        []
#000168c99f29f3b5        fb3046a7d0743b15909d9a7872e651af        ["9"]
#00016cfb8a33e617        62a447a637553f4c85b3b9f642b0adce        []


hive -e "SELECT
      device_id,uuid,
      collect_set(play_duration)      as play_duration
      FROM mds_apache_code_v3
     WHERE dt='20200716'
     GROUP BY device_id,uuid,req_id,timestamp
     limit 100"

#加引号也有结果
你遇到的问题是: ```sql DATE_FORMAT(b2b.issue_date, '%Y-%m-%d') AS dates ``` 输出结果为:`%2021-%4-%15`,这说明 **`DATE_FORMAT` 函数没有正确执行**,而是把格式字符串原样返回了,甚至 `%` 被错误地编码或解析。 --- ## 🔍 问题原因分析 ### ❌ 常见于以下几种情况: | 原因 | 说明 | |------|------| | 1. 使用的是 **Presto/Trino** SQL 引擎 | 它不支持 `DATE_FORMAT()` 函数(这是 MySQL/Hive 的语法) | | 2. `issue_date` 不是标准日期类型 | 可能是字符串(如 `'2021-04-15'`),未转成 `DATE` 类型 | | 3. 格式符被当作普通文本处理 | 导致 `%Y` → 输出为 `%Y` 而不是替换年份 | > ✅ 正确做法取决于你使用的数据库引擎。 --- ## ✅ 解决方案(根据常见 OLAP 引擎) --- ### ✅ 方案一:如果你使用的是 **Presto / Trino** Presto 和 Trino **不支持 `DATE_FORMAT`**,应使用: ```sql DATE_PARSE(date_string, format) -- 字符串转日期 DATE_FORMAT(date, format) -- 日期转指定格式字符串 ``` 但注意:`DATE_FORMAT` 在 Trino 中的格式符是 **`%` 开头的标准 strftime 格式**,且需要字段是 `DATE` 或 `TIMESTAMP` 类型。 #### ✅ 正确写法(Trino/Presto): ```sql -- 如果 issue_dateDATE/TIMESTAMP 类型: DATE_FORMAT(b2b.issue_date, '%Y-%m-%d') AS dates ``` 但如果 `issue_date` 是字符串类型,必须先转为日期: ```sql -- 先用 DATE_PARSE 转成日期,再格式DATE_FORMAT( DATE_PARSE(b2b.issue_date, '%Y-%m-%d'), '%Y-%m-%d' ) AS dates ``` 或者更简洁(假设格式统一): ```sql CAST(b2b.issue_date AS DATE) -- 直接转成 DATE 类型 ``` 然后格式化: ```sql DATE_FORMAT(CAST(b2b.issue_date AS DATE), '%Y-%m-%d') AS dates ``` --- ### ✅ 方案二:如果你使用的是 **HiveQL** Hive 支持 `DATE_FORMAT`,但要求第一个参数是 `DATE` 或 `TIMESTAMP`。 ```sql -- 确保字段是日期类型 DATE_FORMAT(TO_DATE(b2b.issue_date), 'yyyy-MM-dd') AS dates ``` > ⚠️ Hive格式符是 Java 的 `SimpleDateFormat`,所以用 `yyyy-MM-dd`,不是 `%Y-%m-%d` --- ### ✅ 方案三:通用兼容写法(推荐用于 Presto/Trino) 最稳妥的方式是: ```sql -- 将任意字符串日期转为 DATE,再以标准格式输出 CAST( DATE_PARSE(TRIM(b2b.issue_date), '%Y-%m-%d') AS VARCHAR ) AS dates ``` 或者: ```sql -- 直接提取年月日并拼接(适用于简单场景) YEAR(b2b.issue_date) || '-' || LPAD(MONTH(b2b.issue_date), 2, '0') || '-' || LPAD(DAY(b2b.issue_date), 2, '0') AS dates ``` 但这只适合你知道字段已经是 `DATE` 类型的情况。 --- ## 🛠️ 推荐修复步骤 ### 第一步:确认字段类型 ```sql SELECT typeof(b2b.issue_date) FROM b2b LIMIT 1; -- 或 DESCRIBE b2b; ``` - 如果是 `VARCHAR` → 需要先转换 - 如果是 `DATE` 或 `TIMESTAMP` → 可直接格式--- ### 第二步:根据引擎选择正确语法 #### ✅ Presto/Trino 示例(推荐): ```sql SELECT CASE WHEN b2b.issue_date IS NULL THEN NULL ELSE DATE_FORMAT( DATE_PARSE(TRIM(b2b.issue_date), '%Y-%m-%d'), '%Y-%m-%d' ) END AS dates FROM b2b LIMIT 10; ``` 或者如果已是 DATE 类型: ```sql DATE_FORMAT(b2b.issue_date, '%Y-%m-%d') AS dates ``` --- ### 第三步:避免 `%` 被误解析 某些 BI 工具或 JDBC 层会把 `%` 当作占位符。建议: - 升级到最新版客户端 - 使用双百分号 `%%`(部分系统需要) - 或改用纯函数方式拼接 --- ## ✅ 最终推荐写法(兼容性强) ```sql -- 适用于 Presto/Trino,无论输入是字符串还是日期 DATE_FORMAT( COALESCE( TRY(CAST(b2b.issue_date AS DATE)), TRY(DATE_PARSE(b2b.issue_date, '%Y-%m-%d')) ), '%Y-%m-%d' ) AS dates ``` 解释: - `TRY(...)`:防止解析失败报错 - `COALESCE`:尝试多种转换方式 - 最终统一格式化输出 --- ## ✅ 输出验证 正确输出应为: ``` dates -------- 2021-04-15 2025-10-17 ... ``` 而不是 `%2021-%4-%15` --- ## 📝 总结 | 问题 | 原因 | 解决方案 | |------|------|-----------| | 输出 `%2021-%4-%15` | `DATE_FORMAT` 未生效,格式符被当作文本 | 使用正确的 SQL 引擎函数 + 确保日期类型正确 | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值