Zeppelin柱状图按日期排序时1st Sept排在31st Aug前如何修复
修复方案
错误原因
你遇到的分组错误是因为SELECT子句中直接使用了原始行的unix_timestamp(my_timestamp),该值没有经过聚合也没有加入分组条件:同一个按小时聚合的分组内,存在多个不同的原始时间戳,Impala无法确定该返回哪一个值,因此抛出异常。
而最初的排序错误是因为你用格式化后的日期字符串做排序,字符串的字典序会将开头为数字1的1 Sep排在开头为3的31 Aug前面,不符合实际时间顺序。
可行解法
你可以通过子查询先统一把时间按小时截断,再在外层做聚合、排序,既满足显示要求,也能保证排序正确性,参考SQL如下:
%impala SELECT FROM_TIMESTAMP(hour_trunc, 'd MMM HH:mm') AS hours, COUNT(my_number) AS "number per hour" FROM ( SELECT DATE_TRUNC('HOUR', concat(replace(my_timestamp,'"',''), "Z")) AS hour_trunc, my_number FROM my_table WHERE unix_timestamp(my_timestamp) > (unix_timestamp(now()) - 86400) ) t GROUP BY hour_trunc ORDER BY hour_trunc ASC LIMIT 24;
如果你需要保留排序用的时间戳列用于其他逻辑,只需要在SELECT中增加对应字段即可,不会触发分组错误:
%impala SELECT FROM_TIMESTAMP(hour_trunc, 'd MMM HH:mm') AS hours, COUNT(my_number) AS "number per hour", unix_timestamp(hour_trunc) AS sort_ts FROM ( SELECT DATE_TRUNC('HOUR', concat(replace(my_timestamp,'"',''), "Z")) AS hour_trunc, my_number FROM my_table WHERE unix_timestamp(my_timestamp) > (unix_timestamp(now()) - 86400) ) t GROUP BY hour_trunc ORDER BY sort_ts ASC LIMIT 24;
原理说明
- 分组和排序都使用原生的日期类型,避免了字符串字典序的逻辑缺陷
- 所有输出字段要么是分组字段,要么是聚合结果,符合Impala的分组查询语法要求
- 仅在最终输出展示的时候才将日期转为你需要的字符串格式,不影响排序逻辑
内容的提问来源于stack exchange,提问作者Alex Kerr
相关产品推荐
相关产品推荐

