HiveSQL & SparkSQL中常用知识点记录

目录

0. 相关文章链接

1. hive中多表full join主键重复问题

2. Hive中选出最新一个分区中新增和变化的数据

3. Hive中使用sort_array函数解决collet_list列表排序混乱问题

4. SQL中对小数位数很多的数值转换成文本的时候不使用科学计数法

5. HiveSQL & SparkSQL中炸裂函数的使用(列转行)

6. HiveSQL & SparkSQL中对时间的转换


0. 相关文章链接

  开发随笔文章汇总  

1. hive中多表full join主键重复问题

hive中多表full join主键重复问题

2. Hive中选出最新一个分区中新增和变化的数据

Hive中选出最新一个分区中新增和变化的数据

3. Hive中使用sort_array函数解决collet_list列表排序混乱问题

Hive中使用sort_array函数解决collet_list列表排序混乱问题

4. SQL中对小数位数很多的数值转换成文本的时候不使用科学计数法

        我们在SQL中,会碰到使用collect_list和concat_ws将该列的数值统计成一个字段的情况,这时候我们会发现当小数位数太多的时候,有些转换成文本的时候,就会使用科学计数了。如下SQL和图片所示:

select 
    concat_ws('_', collect_list(num))
from (
    SELECT cast(0.000001 as double) as num
    union all
    SELECT cast(0.000009 as double) as num
)
;

        这时如果在应用上需要这个数值进行统计的话,会发现数据错误,所以我们此时,就需要使用特定的方法,将统计出来的文本数据也展示成正常的数据显示(这样在应用上进行切分并获取对应的数据时就能获取到正确的数据);获取方式如下SQL和图片所示:

select 
    concat_ws('_', collect_list(cast(num as DECIMAL(20, 6))))
from (
    SELECT cast(0.000001 as double) as num
    union all
    SELECT cast(0.000009 as double) as num
)
;

核心点:使用cast和decimal保存对应的固有位数,但是要注意decimal中当位数不足时会在后面补0,所以需要注意数值需要的保留位数和固有位数。

5. HiveSQL & SparkSQL中炸裂函数的使用(列转行)

原始数据如下:

select 
    user_id
    ,supply_suppress_score
    ,dt 
FROM yishou_data.dwt_user_preference_score_180day_sp_dt 
where dt = 20230714 and user_id = '25887';

炸裂的语法和展示的数据如下(会新增一列:temp_field):

SELECT
    user_id
    , supply_suppress_score
    , dt
    , temp_field
FROM yishou_data.dwt_user_preference_score_180day_sp_dt
lateral view outer explode (split(supply_suppress_score, ',')) as temp_field
where dt = 20230714 and user_id = '25887'
;

6. HiveSQL & SparkSQL中对时间的转换

  • 函数一:日期时间转日期函数【 to_date() 】
-- to_date(string timestamp) 返回日期时间字段中的日期部分
-- 返回类型:string
-- 其中的cast(xxx as TIMESTAMP)是将对应的秒值转换成TIMESTAMP的毫秒值,会乘以1000

select to_date('2023-06-26 10:03:01') 
-- 输出结果:2023-06-26

select to_date(CAST(1687708800 as TIMESTAMP))
-- 输出结果:2023-06-26
  • 函数二:获取当前日期和时间
-- current_date() 返回当前时间日期
-- 返回类型:date
select current_date()
-- 2023-07-24

-- 通过unix_timestamp和from_unixtime 可以获取当前的时间
select from_unixtime(unix_timestamp(),'yyyy-MM-dd HH:mm:ss')
-- 2023-07-24 16:46:08
  • 函数三:查询当前系统时间(毫秒数 和 秒数) 
-- current_timestamp() 返回当前时间戳
-- 返回类型:timestamp
select current_timestamp() 
-- 1690170111525

-- 时间戳【秒数】
select unix_timestamp()
-- 1690188440
  • 函数四:日期增加函数 【 date_add() 】
-- date_add(string startdate, int days) 返回开始日期startdate增加days天后的日期
-- 返回类型:string

select date_add('2023-07-24', 1)
-- 2023-07-25

select date_add('2023-07-24', -1)
-- 2023-07-23
  • 函数五:日期减少函数:date_sub()
-- date_sub (string startdate, int days) 返回开始日期startdate减少days天后的日期
-- 返回类型:string

select date_sub('2023-07-24', 1) 
-- 2023-07-23

select date_sub('2023-07-24', -1) 
-- 2023-07-25
  • 函数六:日期比较函数:datediff()
-- datediff(string enddate, string startdate) 返回结束日期减去开始日期的天数
-- 返回类型:int

select datediff('2023-07-23','2023-07-21')
-- 2

select datediff('2023-07-23','2023-07-25')
-- -2
  • 函数七:日期格式化,按照格式返回字符串:date_format()
-- date_format(date/timestamp/string, string fmt) 按指定格式返回date
-- 返回类型: string

select date_format('2023-07-23 10:00:00','yyyy-MM-dd') 
--2023-07-23

select date_format('2023-07-23 10:00:00','yyyyMMdd') 
--20230723

select date_format('2023-07-23 10:00:00','yyyy-MM') 
-- 2023-07

select date_format('2023-07-23 10:00:00','yyyy') 
--2023
  • 函数八:日期转换成年、月、日、小时、分钟、秒函数【如果传入字符串需要是日期对应的格式,例:yyyy-MM-dd HH:mm:ss】
-- 日期转年函数:year()
-- year(string/date) 返回时间字符串的年份部分
-- 返回类型:int
select year('2023-07-23 10:00:00') 
-- 2023

-- 日期转月份函数:month()
-- month(string/date) 返回时间字符串的月份
-- 返回类型:int
select month('2023-07-23 10:00:00') 
--7

-- 日期转天函数:day() /dayofmonth(date)
-- day(string/date) 返回时间字符串的天
-- 返回类型:int
select day('2023-07-23 10:00:00') 
--23
select day('2023-07-23') 
--23
select dayofmonth('2023-07-23 10:00:00') 
--23

-- 日期转小时函数:hour()
-- hour(string/date) 返回时间字符串的小时数字
-- 返回类型:int
select hour('2023-07-23 10:00:00') 
--10

-- 日期转分钟函数:minute()
-- minute(string/date) 返回时间字符串的分钟数字
-- 返回类型:int
select minute('2023-07-23 10:00:00') 
--0

-- 日期转秒函数:second()
-- second(string/date) 返回时间字符串的分钟数字
-- 返回类型:int
select second('2023-07-23 10:00:00') 
--0
  • 函数九:月份差:months_between()
-- months_between(date1, date2) 返回date1与date2之间相差的月份,如date1>date2,则返回正,否则为负
-- 返回类型:double

select months_between('2023-07-23','2023-08-25') 
--  -1.06451613

select months_between('2023-07-23','2023-06-25') 
--  0.93548387

select months_between('2023-07-23','2023-07-23') 
--0
  • 函数十:增加月份:add_months()
-- add_months(string start_date, int num_months) 返回当前时间下再增加num_months个月的日期
-- 返回类型:string

select add_months('2023-07-23',2) 
-- 2023-09-23

select add_months('2023-07-23',-2) 
-- 2023-05-23
  • 函数十一:查询时间字符串位于一年中的第几个周内:weekofyear()
-- weekofyear(string/date) 返回时间字符串位于一年中的第几个周内
-- 返回类型:int

select weekofyear('2023-07-23 12:00:00') 
-- 29
  • 函数十二:返回月末: last_day()
-- last_day(string date) 返回这个月的最后一天的日期,忽略时分秒部分(HH:mm:ss)
-- 返回类型:string

select last_day(current_date()) 
-- 2023-07-31

select last_day('2023-07-23') 
-- 2023-07-31

select last_day('2023-07-23 12:00:00') 
-- 2023-07-31
  • 函数十三:返回时间的最开始年份或月份 :trunc()
-- trunc(string date, string format) 返回时间的最开始年份或月份
-- 返回类型:string

select trunc(current_date(),'YY') 
-- 2023-01-01

select trunc('2023-07-23','YY') 
-- 2023-01-01

select trunc(current_date(),'MM') 
-- 2023-07-01

select trunc('2023-07-23','MM') 
-- 2023-07-01
  • 函数十四:返回当月第1天
-- 方案一:使用trunc方法获取最开始的月份
select trunc(current_timestamp(),'MM')
-- 2023-07-01

--方案二:先使用dayofmonth获取当前时间在当月的天数,然后再使用date_sub使用当前日期减去当月天数减一
select date_sub(current_date,dayofmonth(current_date)-1)
-- 2023-07-01
  • 函数十五:返回下个月/上个月第1天
-- 先使用add_months函数加/减一个月,再通过trunc获取这个月的第一天
select trunc(add_months(current_timestamp(),1),'MM')
  • 函数十六:返回下个月/上个月最后1天
-- 先使用add_months函数加/减一个月,再通过trunc获取这个月的第一天,作为第一个参数
-- 先使用add_months函数加/减一个月,再通过last_day获取这个月的最后一天,最后通过dayofmonth获取到这个月有多少天,作为第二个参数
-- 使用date_add函数,将上述第一个参数正常填入,第二个参数减一填入
select date_add(
    trunc(add_months(current_timestamp(),1),'MM') , 
    dayofmonth(last_day(add_months(current_timestamp(),1))) - 1
);
-- 2023-08-31
  • 函数十七:下周几的具体日期: next_day()
-- next_day(string date, string week) 返回当前时间的下一个星期X所对应的日期
-- 返回类型:string
-- 注意:通过next_day和date_sub,还可以用来求取本周几

-- 下周一
select next_day(to_date(CURRENT_TIMESTAMP),'MO') 
-- 2023-07-31

select next_day(CURRENT_DATE,'MO') 
-- 2023-07-31
  • 函数十八:UNIX时间戳转日期函数:from_unixtime()
-- from_unixtime(bigint unixtime[, string format]) 转化UNIX时间戳(从1970-01-01 00:00:00 UTC到指定时间的秒数)到当前时区的时间格式
-- 返回类型:string

select from_unixtime(1323308143,'yyyy-MM-dd') 
--2011-12-08
  • 函数十九:日期转UNIX时间戳函数: unix_timestamp()
-- unix_timestamp(string date) 转换格式为“yyyy-MM-dd HH:mm:ss“的日期到UNIX时间戳。如果转化失败,则返回0
-- 返回类型: bigint

select unix_timestamp('2019-03-07 13:01:03') 
--1551934863

-- unix_timestamp(string date, string pattern) 转换pattern格式的日期到UNIX时间戳。如果转化失败,则返回0
-- 返回类型: bigint

select unix_timestamp('2009-03-20', 'yyyy-MM-dd') 
--1553011200

未完待续......


注:其他相关文章链接由此进 ->  开发随笔文章汇总 


你可能感兴趣的:(开发随笔,大数据,SparkSQL,HiveSQL)