HIVE是一个建立在Hadoop上的数据仓库平台,它提供了一系列的工具,可进行数据提取、转化、加载(ETL),这是一种可以存储、查询、和分析存储在Hodoop中的大规模数据的机制。HIVE定义了简单的类SQL查询语言即HQL,可以将SQL语句转换为MapReduce任务进行运行。
1. ceil(): 向上取最接近的整数;
select ceil(3.1415)
--返回结果:4
2. floor(): 向下取最近的整数;
select floor(3.1415)
--返回结果:3
3. round(): 四舍五入,默认按取整四舍五入,即保留一位小数的浮点型数据,也可指定需保留的小数位;
select round(3.1415)
--返回结果:3.0
select round(3.1415, 3)
--返回结果:3.142
4. abs(): 取绝对值;
select abs( - 3.1415)
--返回结果:3.1415
5. negative(): 取相反数;
select negative(3.1415)
--返回结果:-3.1415
6. sqrt(): 取平方根;
select sqrt(4)
--返回结果:2.0
7. log(): 取对数;
select log(2, 16)
--返回结果(取以2为底16的对数):4.0
8. pow()、power(): 计算次方;
select pow(2, 4)
--返回结果(计算2的4次方):16.0
select power(2, 4)
--返回结果(计算2的4次方):16.0
9. bin(): 进制转换,十进制转换为二进制;
select bin(100)
--返回结果:1100100
10. hex(): 进制转换,十进制转换为十六进制;
select hex(100)
--返回结果:64
11. conv(): 进制转换,将某进制转换为其他进制;
select conv(1100100, 2, 16)
--返回结果(将二进制的1100100转换为十六进制):64
12. pi(): 圆周率常数;
select pi()
--返回结果:3.141592653589793
13. degrees(): 弧度化为角度;.
select degrees(pi())
--返回结果(圆周率Pi弧度对应的角度为180度):180.0
14. radians(): 角度化为弧度;
select radians(180)
--返回结果(180度角对应的弧度为圆周率Pi):3.141592653589793
15. sin()、cos()、tan()、asin()、acos()、atan(): 分别取正弦、余弦、正切、反正弦、反余弦、反正切值,注意参数值为弧度,非角度值;
select sin(radians(30))
--返回结果:0.49999999999999994
select cos(radians(30))
--返回结果:0.8660254037844387
select tan(radians(30))
--返回结果:0.5773502691896257
select asin(radians(30))
--返回结果:0.5510695830994463
select acos(radians(30))
--返回结果:1.0197267436954502
select atan(radians(30))
--返回结果:0.48234790710102493
16. sign(): 正数返回1.0,负数返回-1.0,否则返回0.0;
select sign(3.1415)
--返回结果:1.0
select sign( - 3.1415)
--返回结果:-1.0
select sign(0)
--返回结果:0.0
17. percentile()、percentile_approx(): 分位数函数,取表某列的分位数,用法为percentile(col_name,p),percentile_approx(col_name,p),其中p取值为[0, 1],如p=0、0.25、0.5、0.75、1等,分别代表列中的最小值、下四分位数、中位数、上四分位数、最大值等,也可传入数组即同时取出多个分位数;
--percentile函数入参的列值必须为int类型,对于非int类型的列可通过int()或cast()函数将其数据类型转换成int型;
select
percentile(col_name, 0.5)
from
table_name
--返回结果(结果为double类型):表中col_name列的中位数
--percentile_approx函数入参的列值为数值类型即可,该函数还可以传入一个精度参数B,不传默认B为10000,即形式为percentile_approx(col_name,p,B),当所求分位数的列值去重数小于精度B时,返回的分位数为准确值,当去重数大于精度时,返回的分位数为按精度取舍得出的分位数,非准确值;
select
percentile_approx(col_name, 0.5)
from
table_name
--返回结果(结果为double类型):表中col_name列的中位数
select
percentile(col_name, array(0.25, 0.5, 0.75))
from
table_name
--返回结果:以数组形式呈现表中col_name列的下四分位数、中位数、上四分位数,如[25.0,50.0,75.0]
select
percentile_approx(col_name, array(0.25, 0.5, 0.75),9999)
from
table_name
--返回结果:控制精度为9999,以数组形式呈现表中col_name列的下四分位数、中位数、上四分位数,如[25.0,50.0,75.0]
1. to_date(): 返回时间中至日期的部分,格式为YYYY-MM-DD,类似用法还有to_month()、to_year()、to_quarter(),分别返回日期中至月份(YYYY-MM)、年份(YYYY)、季节(YYYYQ1、YYYYQ2等)部分的数据;
select to_date('2020-12-02 20:20:40')
--返回结果:2020-12-02
select to_date('2020-12-02')
--返回结果:2020-12-02
2. datediff(): 返回两个时间之间的天数差;
select datediff('2020-12-02 20:20:30', '2019-06-20 18:20:30')
--返回结果:531
select datediff('2020-12-02', '2019-06-20')
--返回结果:531
select datediff('2019-06-20 18:20:30', '2020-12-02 20:20:30')
--返回结果:-531
3. date_add(): 返回指定日期增加某些天数之后的日期,类似用法还有month_add(),返回指定月份差的日期;
select date_add('2020-12-02 20:20:30', 10)
--返回结果:2020-12-12
select date_add('2020-12-02 20:20:30', - 10)
--返回结果:2020-11-22
select date_add('2020-12-02', 10)
--返回结果:2020-12-12
4. date_sub(): 返回指定日期减少某些天数的日期;
select date_sub('2020-12-02 20:20:30', 10)
--返回结果:2020-11-22
select date_sub('2020-12-02 20:20:30', - 10)
--返回结果:2020-12-12
select date_sub('2020-12-02', 10)
--返回结果:2020-11-22
5. second()、minute()、hour()、day()、week()、month()、year(): 返回给定时间的秒、分、时、天、周、月、年相关信息;
select second('2020-12-02 20:20:30')
--返回结果:30
select day('2020-12-02 20:20:30')
--返回结果:2
select year('2020-12-02 20:20:30')
--返回结果:2020
6. weekofyear(): 返回指定时间在一年中的周数;
select weekofyear('2020-12-02 20:20:30')
--返回结果(2020-12-02属于2020年的第49周):49
select weekofyear('2020-12-02')
--返回结果(2020-12-02属于2020年的第49周):49
7. unix_timestamp(): 将时间转换成时间戳,若不传参返回当前时间戳;
select unix_timestamp('2020-12-02 20:20:20')
--返回结果:1606911620
select unix_timestamp()
--返回结果:1606904577
8. from_unixtime(): 将时间戳转换成日期形式;
select from_unixtime(1606911620)
--返回结果:2020-12-02 20:20:20
select from_unixtime(unix_timestamp())
--返回结果(获取当前时间):2020-12-02 18:26:20
9. current_date(): 获取当前的日期,格式为YYYY-MM-DD;
select current_date()
--返回结果:2020-12-02
10. current_timestamp(): 获取当前系统时间,精确到毫秒;
select current_timestamp()
--返回结果:2020-12-02 18:29:19.161
1. length(): 返回字符串长度;
select length('abcde')
--返回结果:5
2. concat(): 字符串合并函数,将多个字符串合并成一个字符串;
select concat('ab', 'cd', 'ef')
--返回结果:abcdef
select concat('ab', NULL, 'cd', 'ef')
--返回结果(NULL为未知,拼接后的结果仍然未知,因此结果为NULL):NULL
select concat('ab', '', 'cd', 'ef')
--返回结果(空就是没有,等于没有拼接什么,因此ab,cd直接拼接,结果为abcdef):abcdef
select concat('ab', ' ', 'cd', 'ef')
--返回结果(空格是实实在在的东西,不是空(没东西)和NULL(未知,即有没有或者有的话是什么,均不得知),因此相当于ab,cd之间拼接了一个空格,结果为ab cdef):ab cdef
3. concat_ws(): 字符串合并函数,concat_ws(char, str1, str2, str3, …)将多个字符串按照指定拼接符合并在一起;
select concat_ws('#', 'ab', 'cd', 'ef')
--返回结果:ab#cd#ef
4. reverse(): 字符串反转;
select reverse('abcdef')
--返回结果:fedcba
5. lpad(): 返回指定长度的字符串,给定字符串长度小于指定长度时,由指定字符从左侧填补,用法为lpad(string str1, int len, string str2),当len小于等于str1的长度时直接返回str1对应长度的字符串,当len大于str1长度时,str1左侧填补str2至满足len的长度再返回填补后的字符串;
select lpad('abcdef', 10, 'q')
--返回结果:qqqqabcdef
select lpad('abcdef', 4, 'q')
--返回结果:abcd
6. rpad(): 返回指定长度的字符串,给定字符串长度小于指定长度时,由指定字符从右侧填补,用法为rpad(string str1, int len, string str2),当len小于等于str1的长度时直接返回str1对应长度的字符串,当len大于str1长度时,str1右侧填补str2至满足len的长度再返回填补后的字符串;
select rpad('abcdef', 10, 'q')
--返回结果:abcdefqqqq
select rpad('abcdef', 4, 'q')
--返回结果:abcd
7. upper(): 大写转换,将字符串转换成大写;
select upper('abcdef')
--返回结果:ABCDEF
select upper('abcdef12#')
--返回结果:ABCDEF12#
8. lower(): 小写转换,将字符串转换成小写;
select lower('ABCDEF')
--返回结果:abcdef
select lower('ABCDEF12#')
--返回结果:abcdef12#
9. trim(): 删除字符串两端的空格,字符之间的空格保留;
select trim(' abc def ')
--返回结果:abc def
10. ltrim(): 删除字符串左边的空格,其他的空格保留;
select ltrim(' abc def ')
--返回结果:abc def
select length(ltrim(' abc def '))
--返回结果:8
11. rtrim(): 删除字符串右边的空格,其他的空格保留;
select rtrim(' abc def ')
--返回结果: abc def
select length(rtrim(' abc def '))
--返回结果:8
12. substr()、substring(): 字符串截取函数,二者用法一致,substr(string str , int start , int len),将表达式从start位置开始(位置从1起,负值表示从末尾倒数),截取长度为len的字符串,不指定len则默认从指定位置截取到字符串末尾;
select substr('abcdefg',3)
--返回结果:cdefg
select substr('abcdefg',3,3)
--结果返回:cde
select substring('abcdefg', - 3)
--返回结果:efg
select substring('abcdefg', - 3,2)
--结果返回:ef
13. substring_index: 字符串截取函数,sub_string_index(string str1,string str2,index),以某字符为分隔符,返回索引指定数量分隔符前后的部分,若索引为正数N,表示返回表达式中从左往右数第N个分隔符左边的全部内容,若为负数N,则表示返回表达式中从右往左数第N个分隔符右边的全部内容;
select substring_index('www.baidu.com', '.', 2)
--返回结果:www.baidu
select substring_index('www.baidu.com', '.', -2)
--结果返回:baidu.com
select substring_index(substring_index('www.baidu.com', '.', 2), '.', - 1)
--返回结果(可通过左右两边截取中间字符):baidu
14. instr(): 索引函数,instr(string str1 , string str2)返回表达式中指定字符第一次出现的位置(位置号从1起);
select instr('abcdef', 'c')
--返回结果:3
15. cast(): 类型转换,cast(express as type)将表达式转换成某种类型类型;
select cast(123 as int)
--返回结果:123
16. coalesce(): 非空查找函数,在多个表达式中,取第一个不为null的值,若均为null,则返回null;
select coalesce(NULL, 'abc', '123')
--返回结果:abc
17. nvl(): 空值替换函数,nvl(str1 , str2),当str1为空时返回str2,str1不为空时返回str1;
select nvl(NULL, 'abc')
--返回结果:abc
select nvl('def', 'abc')
--返回结果:def
1. count(): 计算总行数,注意count()计算行数会忽略空行,可与distinct联用计算去重行数;
select count(1) from table_name
--计算表中总行数,空行会忽略
select count(*) from table_name
--计算表中总行数,空行会忽略
select count(col_name) from table_name
--计算表中col_name列的总行数,空行会忽略
select count(DISTINCT col_name) from table_name
--计算表中col_name列的去重总行数,空行会忽略
2. sum(): 求和函数,返回某列数据的总和,可与distinct联用,返回某列去重后数据的总和;
SELECT SUM(col_name) FROM table_name
SELECT SUM(DISTINCT col_name) FROM table_name
3. avg(): 平均值函数,返回某列中数据的平均值,可与distinct联用返回某列去重后数据的平均值;
SELECT AVG(col_name) FROM table_name
SELECT AVG(DISTINCT col_name) FROM table_name
4. max()、min(): 最大最小值函数,返回某列中最大、最小值;
SELECT MAX(col_name) FROM table_name
SELECT MIN(col_name) FROM table_name
5. variance()、var_pop(): 方差函数,返回某列数据的方差,可与distinct联用返回某列去重后数据的方差;
SELECT VARIANCE (col_name) FROM table_name
SELECT VAR_POP (DISTINCT col_name) FROM table_name
6. stddev()、stddev_pop(): 标准差函数,返回某列数据的标准差,可与distinct联用返回某列去重后数据的标准差;
SELECT STDDEV (col_name) FROM table_name
SELECT STDDEV_POP (DISTINCT col_name) FROM table_name
1. split(): 切分,字符串切割函数,split(str,char)将字符串str按照字符char进行切分;
select split('abc_def', '_')
--返回结果:["abc","def"]
select split('abc_def', '_')[0]
--返回结果:abc
select split('abc_def', '_')[1]
--返回结果:def
2. explode(): 转置,行转列函数,接受array或map类型参数,将数组中每个元素生成一行或将map类型中的每个key-value生成一行,key和value各一列;
select explode(split('abc_def', '_'))
--返回结果:
--1 abc
--2 def
3. lateral view(): 侧视图,配合explode、split等函数一起使用,用于呈现将单行数据拆解成多行数据后的结果集,相当于生成一个虚拟表,该语句可多重使用。结合1、2、3举例:如下表table_name有col1、col2、col3三列数据
col1 | col2 | col3 |
---|---|---|
1 | [a,b] | 1_2_3 |
2 | [c,d] | 4_5_6 |
1) 按照col3的下划线进行行转列:
select
col1,
col2,
col3,
new_col
from
table_name lateral VIEW explode(split(col3, '_')) new_table AS new_col
即生成新的虚拟表(new_table)其中包含新列(new_col),结果如下表:
col1 | col2 | col3 | new_col |
---|---|---|---|
1 | [a,b] | 1_2_3 | 1 |
1 | [a,b] | 1_2_3 | 2 |
1 | [a,b] | 1_2_3 | 3 |
2 | [c,d] | 4_5_6 | 4 |
2 | [c,d] | 4_5_6 | 5 |
2 | [c,d] | 4_5_6 | 6 |
2) 按照col2和col3两列进行行转列,col2数组直接用explode行转列,col3先按照下划线切分再行转列,两个lateral view连用:
select
col1,
col2,
col3,
new_col1,
new_col2
from
table_name lateral VIEW explode(col2) new_table1 AS new_col1 lateral view explode(split(col3, '_')) new_table2 as new_col2
即生成两张虚拟表(new_table1和new_table2)和两个新列(new_col1和new_col2),其最终展示的结果为原表和两张虚拟表的笛卡尔积,结果如下表:
col1 | col2 | col3 | new_col1 | new_col2 |
---|---|---|---|---|
1 | [a,b] | 1_2_3 | a | 1 |
1 | [a,b] | 1_2_3 | a | 2 |
1 | [a,b] | 1_2_3 | a | 3 |
1 | [a,b] | 1_2_3 | b | 1 |
1 | [a,b] | 1_2_3 | b | 2 |
1 | [a,b] | 1_2_3 | b | 3 |
2 | [c,d] | 4_5_6 | c | 4 |
2 | [c,d] | 4_5_6 | c | 5 |
2 | [c,d] | 4_5_6 | c | 6 |
2 | [c,d] | 4_5_6 | d | 4 |
2 | [c,d] | 4_5_6 | d | 5 |
2 | [c,d] | 4_5_6 | d | 6 |
4. collect_all()、collect_list()、collect_set(): 列转行函数,需搭配group by使用,将分组中某列对应的字段值以数组的形式返回, collect_all()和collect_list()返回所有值不去重,collect_set()做去重处理;
举例: 如下表table_name,有col1、col2、col3三列:
col1 | col2 | col3 |
---|---|---|
1 | a | A |
1 | a | A |
1 | a | B |
2 | b | A |
2 | b | A |
2 | b | B |
select
col1,
collect_all(col2) new_col--或者collect_list(col2)
from
table_name
group by
col1
返回结果如下表:
col1 | new_col |
---|---|
1 | [“a”,“a”,“a”] |
2 | [“b”,“b”,“b”] |
select
col1,
collect_set(col2) new_col
from
table_name
group by
col1
返回结果如下表:
col1 | new_col |
---|---|
1 | [“a”] |
2 | [“b”] |
select
col1,
col2,
collect_all(col3) new_col--或者collect_set(col3)
from
table_name
group by
col1,
col2
返回结果如下表:
col1 | col2 | new_col |
---|---|---|
1 | a | [“A”,“A”,“B”] |
2 | b | [“A”,“A”,“B”] |
select
col1,
col2,
collect_set(col3) new_col
from
table_name
group by
col1,
col2
返回结果如下表:
col1 | col2 | new_col |
---|---|---|
1 | a | [“A”,“B”] |
2 | b | [“A”,“B”] |
5.count()、group by、having count(): 分组去重统计,group by进行分组去重,count()对分组进行统计,having count()将分组统计后满足一定条件的组展示出来,起到筛选分组的作用;
举例: 如下表table_name,有col1、col2、col3三列:
col1 | col2 | col3 |
---|---|---|
1 | a | 90 |
1 | a | 95 |
2 | B | 98 |
2 | B | 98 |
3 | C | 100 |
3 | C | 100 |
3 | C | 100 |
1) 按col1列进行分组计数;
select
col1,
COUNT(1) num
from
table_name
group by
col2
having
count(1) > 1;
返回结果如下表:
col2 | num |
---|---|
1 | 2 |
2 | 2 |
3 | 3 |
2) 按照col1、col2、col3三列进行分组计数,将分组后col2列大于1次和col3列小于3次的分组展示出来;
select
col1,
col2,
COL3
COUNT(1) num
from
table_name
group by
col1,
col2,
col3
having
count(col2) > 1
AND count(col3) < 3;
返回结果如下表:
col2 | col3 | num |
---|---|---|
2 | B | 2 |
6.join(inner join)、full join(full outer join)、left join(left outer join)、right join(right outer join): 表关联函数,分别为两表之间的内连接、全连接、左连接、右链接;
举例: 如下两个表table_name1和table_name2:
table_name1:
col1 | col2 |
---|---|
Damon | a |
Stefan | b |
Ella | c |
table_name2:
col1_1 | col2_2 |
---|---|
Damon | a |
Stefan | b |
Lisa | c |
1)join(inner join): 根据关联条件,两表之间能匹配上的行被保留,匹配不上的行被丢弃,即取两表的交集;
SELECT
*
FROM
table_name1
JOIN table_name2
ON
table_name1.col1 = table_name2.col1_1 ;
返回结果如下表:
col1 | col2 | col1_1 | col2_2 |
---|---|---|---|
Damon | a | Damon | a |
Stefan | b | Stefan | b |
2)full join(full outer join): 返回两表中的所有行,根据关联条件两表之间匹配不上的行其对应的字段值为空,即取两表的并集;
SELECT
*
FROM
table_name1
FULL JOIN table_name2
ON
table_name1.col1 = table_name2.col1_1 ;
返回结果如下表:
col1 | col2 | col1_1 | col2_2 |
---|---|---|---|
Damon | a | Damon | a |
Stefan | b | Stefan | b |
Ella | c | NULL | NULL |
NULL | NULL | Lisa | c |
3)left join(left outer join): 以左表为基准,返回左表的所有行,右表根据关联条件与左表匹配不上的行,字段值为空;
SELECT
*
FROM
table_name1
LEFT JOIN table_name2
ON
table_name1.col1 = table_name2.col1_1 ;
返回结果如下表:
col1 | col2 | col1_1 | col2_2 |
---|---|---|---|
Damon | a | Damon | a |
Stefan | b | Stefan | b |
Ella | c | NULL | NULL |
4)right join(right outer join): 以右表为基准,返回右表的所有行,左表根据关联条件与右表表匹配不上的行,字段值为空;
SELECT
*
FROM
table_name1
RIGHT JOIN table_name2
ON
table_name1.col1 = table_name2.col1_1 ;
返回结果如下表:
col1 | col2 | col1_1 | col2_2 |
---|---|---|---|
Damon | a | Damon | a |
Stefan | b | Stefan | b |
NULL | NULL | Lisa | c |
7. regexp_replace: 正则替换,regexp_replace(str, ‘str1’, ‘str2’),将表达式str中的str1全部替换成str2;
select regexp_replace('case1_case2_case3', '_', '#')
--返回结果:case1#case2#case3
8. regexp_extract: 正则匹配函数,regexp_extract(str, regexp, index),将表达式str按照正则部分regexp进行拆分,返回指定索引的部分;index=0:返回与正则表达式匹配的整个字符串,index=1、2、3、4…:分别返回正则表达式中第一、二、三、四…个括号内的字符串,不写index参数则默认为1;
select regexp_extract('form&source=a&flag=login', '&(source=.+)&(.*)')
--返回结果(index默认为1):source=a
select regexp_extract('form&source=a&flag=login', '&(source=.+)&(.*)', 0)
--返回结果:&source=a&flag=login
select regexp_extract('form&source=a&flag=login', '&(source=.+)&(.*)', 1)
--返回结果:source=a
select regexp_extract('form&source=a&flag=login', '&(source=.+)&(.*)', 2)
--返回结果:flag=login
9. get_json_object(): json类型解析函数,get_json_object(json, ‘$.kye’),解析json中指定key对应的value;
select get_json_object('{"name":"Lisa","score":"99"}', '$.name')
--返回结果:Lisa
10. parse_url(): url截取函数,用法为parse_url(url, key),其中key可为HOST、PATH、QUERY、REF、PROTOCOL、FILE、AUTHORITY、USERINFO];
select parse_url('http://facebook.com/path/p1.php?query=1', 'PROTOCOL')
--返回结果:http
select parse_url('http://facebook.com/path/p1.php?query=1', 'HOST')
--返回结果:facebook.com
select parse_url('http://facebook.com/path/p1.php?query=1', 'REF')
--返回结果:NULL
select parse_url('http://facebook.com/path/p1.php?query=1', 'PATH')
--返回结果:/path/p1.php
select parse_url('http://facebook.com/path/p1.php?query=1', 'QUERY')
--返回结果:query=1
select parse_url('http://facebook.com/path/p1.php?query=1', 'FILE')
--返回结果:/path/p1.php?query=1
select parse_url('http://facebook.com/path/p1.php?query=1', 'AUTHORITY')
--返回结果:facebook.com
select parse_url('http://facebook.com/path/p1.php?query=1', 'USERINFO')
--返回结果:NULL
11. if(): 条件判断函数,if(condition, true_value, false_value),根据判断条件为true或false返回对应的值;
select if(1 > 2, 'abc', 'def')
--返回结果:def
12. case when三种用法: 根据某列值返回符合条件的对应值。举例: 如下表table_name,有id,col1,col2三列数据:
id | col1 | col2 |
---|---|---|
1 | a | A |
2 | b | B |
3 | c | C |
select
id,
col1,
col2,
case
when id = 1
then 'test1'
when id = 2
then 'test2'
else 'test3'
end as new_col1,
case id
when 1
then 'test1'
when 2
then 'test2'
else 'test3'
end as new_col2,
case
when id = 1
then col1
else col2
end as new_col3,
case
when id = 1
then 'test1'
when id = 2
then 'test2'
end as new_col4,
case id
when 1
then 'test1'
when 2
then 'test2'
end as new_col5,
case
when id = 1
then col1
when id = 2
then col2
end as new_col6
from
table_name
返回结果如下表:
id | col1 | col2 | new_col1 | new_col2 | new_col3 | new_col4 | new_col5 | new_col6 |
---|---|---|---|---|---|---|---|---|
1 | a | A | test1 | test1 | a | test1 | test1 | a |
2 | b | B | test2 | test2 | B | test2 | test2 | B |
3 | c | C | test3 | test3 | B | NULL | NULL | NULL |
13. row_number()over()、dense_rank()over()、rank()over(): 分组排序,row_number()over(partition by col1 order by col2 desc)表示按照col1列分组,分组后组内按照col2列进行降序排列,dense_rank、rank用法与row_number一致。注意:row_number排序,序号依次递增不跳跃,组内数据相同序号不同,如1、2、3、4…;dense_rank排序,序号递增不跳跃,组内数据相同序号相同,如1、1、2、3…;rank排序,序号不连续存在跳跃,组内数据相同序号相同,如1、1、3、4…
举例: 如下表table_name,有name、subject、score三列;
name | subject | score |
---|---|---|
Stefan | Math | 98 |
Stefan | Chinese | 93 |
Damon | Math | 100 |
Damon | Chinese | 90 |
Ella | Math | 98 |
Ella | Chinese | 93 |
Lisa | Math | 95 |
Lisa | Chinese | 96 |
select
name,
subject,
score,
row_number() over(partition by subject order by score desc) row_number,
dense_rank() over(partition by subject order by score desc) dense_rank,
rank() over(partition by subject order by score desc) rank
from
table_name
返回结果如下表:
name | subject | score | row_number | dense_rank | rank |
---|---|---|---|---|---|
Lisa | Chinese | 96 | 1 | 1 | 1 |
Ella | Chinese | 93 | 2 | 2 | 2 |
Stefan | Chinese | 93 | 3 | 2 | 2 |
Damon | Chinese | 90 | 3 | 3 | 4 |
Damon | Math | 100 | 1 | 1 | 1 |
Ella | Math | 98 | 2 | 2 | 2 |
Stefan | Math | 98 | 3 | 2 | 2 |
Lisa | Math | 95 | 4 | 3 | 4 |
1)直接建表法:
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
[(col_name data_type [COMMENT col_comment], ...)]
[COMMENT table_comment]
[PARTITIONED BY(col_name data_type [COMMENT col_comment], ...)]
[CLUSTERED BY (col_name, col_name, ...)
[SORTED BY(col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS]
[ROW FORMAT row_format]
[STORED AS file_format]
[LOCATION hdfs_path]
--关键词解释如下:
--CREATE TABLE:创建一个指定名字的表,若同名表已存在会报错,加上IF NOT EXISTS若存在同名表不会报错,但建表不会成功,表结构依然是原来已存在的同名表;
--EXTERNAL:创建外部表,默认是内部表;
--COMMENT:给表字段或者表内容添加注释说明;
--PARTITIONED BY:给表做分区,分区字段不可与create建表时指定的表字段重复,即分区字段只出现在partition by中,不可重复出现在table_name后面指定的字段中;
--CLUSTERED BY:对表或分区进行分桶,桶为更细粒度的数据范围;
--ROW FORMAT DELIMITED FIELDS TERMINATED BY ',':指定表存储中列的分隔符,默认是 \001,此处指定以逗号分隔;
--STORED AS SEQUENCEFILE|TEXTFILE|RCFILE:指定数据文件的格式,STORED AS TEXTFILE表示数据文件为纯文本,如果数据需要压缩,可用STORED AS SEQUENCEFILE;
--LOCATION:指定hive表中数据在hdfs上的存储路径.
举例: 以下以dt字段为分区创建一张名为table_name的分区表:
CREATE
TABLE IF NOT EXISTS table_name
(
name VARCHAR(20) COMMENT '表第一列',
subject VARCHAR(20) COMMENT'表第二列'
)
COMMENT '测试表' PARTITIONED BY
(
dt string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
表创建成功后,导入一行数据,结果如下:
name | subject | dt |
---|---|---|
Lisa | Math | 2020-12-02 |
2)查询建表法: 将子查询的结果(table_name中的查询结果)存在新表new_table中,通过as查询语句完成建表:
CREATE TABLE IF NOT EXISTS new_table AS
SELECT name,dt FROM table_name
new_table如下:
name | dt |
---|---|
Lisa | Math |
3)like建表法: 创建结构完全相同的表,仅创建表结构,无数据:
CREATE TABLE IF NOT EXISTS new_table LIKE table_name
new_table如下:
name | subject | dt |
---|---|---|
1)truncate table: 删除表数据,保留表结构,用法为语句后直接加表名;
TRUNCATE TABLE table_case
2)drop table: 删除整个表,表结构和表数据全部清除,用法为语句后直接加表名;
DROP TABLE table_case
3)delete: 删除表中特定条件下的行;
DELETE FROM table_case WHERE name = 'Lisa'
--删除table_case中name为Lisa的数据,若指定WHERE 1=1,则删除所有行
1)show create table: 查看建表语句;
show
CREATE TABLE table_name
2)show partitions: 查看表分区;
show partitions table_name
3)desc: 查看表结构,即查看表字段、字段类型、字段注释以及表分区;
DESC table_name
4)desc formatted: 查看表详细属性,除表字段、字段类型、字段注释以及表分区外还会展示表详细信息如所属数据库、负责人、创建时间等;
DESC formatted table_name
5)dfs -du: 查看表某个分区下文件大小(文件路径可从查看表详细或建表语句的LOCATION中获取):
dfs -du hdfs://snd10101/user/mobile_market/dev.db/table_case/dt=2020-12-02/name_partition=L
---格式为dfs - du ***(表路径)/***(分区,可指定多个分区)
1)视图: 视图是一张虚表,只存储sql语句,不存储数据;
举例:如表table_name,有name、subject、dt三列数据;
name | subject | dt |
---|---|---|
Lisa | Math | 2020-12-02 |
create view view_name as
select * from table_name
创建视图(view_name)如下:
name | subject | dt |
---|---|---|
Lisa | Math | 2020-12-02 |
2)物化视图: 物化视图可理解为一张表,其真实存储数据;
举例:如表table_name,有name、subject、dt三列数据;
name | subject | dt |
---|---|---|
Lisa | Math | 2020-12-02 |
create materialized view view_name
as
select * from table_name
创建物化视图(view_name)如下:
name | subject | dt |
---|---|---|
Lisa | Math | 2020-12-02 |
索引是为了提高表中数据行的检索效率而创建的数据结构,索引可以大大提高数据的查询速度。
索引是将表的某列值及其值对应数据行的物理地址进行存储,查询时直接根据索引对应的地址返回相关数据行,极大提高了查询速度。根据索引中包含的列数可将索引分为单列索引(索引中只包含一个列)和组合索引(索引中包含多个列);
举例: 如下表table_name,有id、name、score三列,其中斜体的磁盘地址表示每行数据的存储地址,非表本身数据。以id列建立索引示意图如下:
table_name:
磁盘地址 | id | name | score |
---|---|---|---|
0x1234 | 1 | Lisa | 95 |
0x1235 | 2 | Ella | 98 |
0x1236 | 3 | Damon | 90 |
… | … | … | … |
以id列建立的索引:
1 | 0x1234 |
---|---|
2 | 0x1235 |
3 | 0x1236 |
… | … |
假如表table_name中有100万条数据,要取出id=10000的数据行,在无索引的情况下,需要将100万条数据全部遍历完,然后返回id=10000的数据行,查询速度较慢;而在以id列建立索引的情况下,则无需遍历数据,直接根据索引找到id=10000所在行的地址然后返回数据,极大提高了查询速度,二者的查询效率可想而知;
索引的优点显而易见,它可以极大提高数据的查询速度,同时索引的缺点也很明显,主要是占用磁盘空间(因为索引的数据结构需要存储)和降低表更新的速度(因为对于数据表的增、删、改操作索引也要随之变动);
1.group by 后字段必须全部包含select 中的字段: group by执行顺序在select前,由于group by对字段进行分组去重,分组以外的字段将被合并,若select后选择分组去重字段以外的字段,则无法明确选中字段的值,因为这些字段已经被合并,因此程序会报错;
2.order by实现排序的同时也实现了分组: order by按照某字段升序或降序(desc),由于相同值会排在一起,因此排序的同时也实现了分组,如order by name, score desc即先按照姓名升序排列,同名的排在一起,然后同组之间再按照分数降序排列,这样也就实现了先分组然后组内再排序的功能;
1.引流: 提取3个月内未访问过客户端,由活动再次访问客户端的用户数,活动周期2020-12-19至2021-01-05;
1)第一种方法: 先取出3个月内访问过客户端且访问了活动的用户,再将这部分用户从访问过活动的总用户中剔除;
SELECT
d.dt,
COUNT(DISTINCT d.user_log_acct) num
FROM
(
SELECT
dt,
user_log_acct
FROM
user_table
WHERE
dt BETWEEN'2020-12-19' AND '2021-01-05'
AND 活动页条件限定
GROUP BY
dt,
user_log_acct
)
d
LEFT JOIN
(
SELECT
a.dt,
a.user_log_acct
FROM
(
SELECT
dt,
user_log_acct
FROM
user_table
WHERE
dt BETWEEN'2020-12-19' AND '2021-01-05'
AND 活动页条件限定
GROUP BY
dt,
user_log_acct
)
a
LEFT JOIN
(
SELECT
dt,
user_log_acct
FROM
user_table
WHERE
dt BETWEEN '2020-09-19' AND '2021-01-04'/*注意,总用户的时间范围为活动周期开始时间向前推3个月至活动最后一天向前推一天*/
GROUP BY
dt,
user_log_acct
)
b
ON
a.user_log_acct = b.user_log_acct
WHERE
DATEDIFF(a.dt, b.dt) BETWEEN '1' AND '90'
GROUP BY
a.dt,
a.user_log_acct
)
c ON d.dt = c.dt
AND d.user_log_acct = c.user_log_acct
WHERE
c.user_log_acct IS NULL
GROUP BY
d.dt
ORDER BY
d.dt ;
2)第二种方法: 对用户进行打标,将3个月内访问过客户端且访问过活动的用户记成sort=1,三个月内未访问过客户端然后通过活动再次访问了客户端的用户记为sort=0,sum(sort)=0的就是满足三个月内未访问过客户端通过活动再次访问客户端的用户;
SELECT
d.dt,
COUNT(DISTINCT user_log_acct) num
FROM
(
SELECT
c.dt,
c.user_log_acct
FROM
(
SELECT
a.dt,
a.user_log_acct,
CASE
WHEN DATEDIFF(a.dt, b.dt) BETWEEN '1'AND '90'
THEN 1
ELSE 0
END AS sort
FROM
(
SELECT
dt,
user_log_acct
FROM
user_table
WHERE
dt BETWEEN'2020-12-19' AND '2021-01-05'
AND 活动页条件限定
GROUP BY
dt,
user_log_acct
)
a
LEFT JOIN
(
SELECT
dt,
user_log_acct
FROM
user_table
WHERE
dt BETWEEN '2020-09-19' AND '2021-01-04'/*注意,总用户的时间范围为活动周期开始时间向前推3个月至活动最后一天向前推一天*/
GROUP BY
dt,
user_log_acct
)
b
ON
a.user_log_acct = b.user_log_acct
)
c
GROUP BY
c.dt,
c.user_log_acct
HAVING
SUM(sort) = 0
)
d
GROUP BY
d.dt
ORDER BY
dt;
2.连签:取近7天连续签到的用户数
SELECT
COUNT(DISTINCT a.user_log_acct) AS num
FROM
(
SELECT
user_log_acct,
COUNT(DISTINCT dt) AS uniq_dt
FROM
user_table
WHERE
dt >= sysdate( - 7)
AND dt <= sysdate( - 1)
AND 用户签到限定条件
GROUP BY
user_log_acct
)
a
WHERE
a.uniq_dt = '7';
3.复访:
4.留存
5.假设表有id和value两列,取满足条件的value值: 当id字段中最大值>=6时取id=6对应的value字段值,当id中最大值<6则取最大的id值对应的value值,sql如下:
SELECT
value
FROM
table_name
WHERE
id IN
(
SELECT
CASE
WHEN MAX(id) >= 6
THEN 6
ELSE MAX(id)
END AS NEW_column
FROM
tablename
)
--根据某列值的情况返回另一列对应的值,与case when功能一致,此sql case when产生的新列只有一个数据,可将其嵌套在where中使用,做到根据一列的值取另一列的值;
6.解析json中指定的key: 从如下json中解析出shopid;
{ “ordernum”: “111”, “shopnumber”: “222”, “shop”: [{ “shopid”: “666”, “shoptype”: “777”}, { “shopid”: “222”, “shoptype”: “111”}] }
SELECT
explode(split(regexp_replace(regexp_replace(get_json_object('{"ordernum": "111", "shopnumber": "222", "shop": [{ "shopid": "666", "shoptype": "777"},{ "shopid": "222", "shoptype": "111"}]}', '$.shop'), '\\[|\\]', ''), '\\}\\,\\{', '}#{'), '#'))
--sql解析:
--1.先get_json_object()解析出shop,解析出的值为数组格式;
--2.连用两个正则替换regexp_replace()先将数组中的前后中括号[]替换成空,即去掉中括号,再将各json中的},{替换成}#{,便于后续使用split()按照#切分出各个单独的json;
--3.用行转列函数explode将切分后的各个json转成行,每个json单独成一行。
--返回结果:
--1 {"shopid":"666","shoptype":"777"}
--2 {"shopid":"222","shoptype":"111"}
7.不用分位数函数求表table_name中score列的中位数:
select
avg(tem_table.score)
from
(
select
score,
row_number() over(order by score) rank
from
table_name
)
tem_table
where
tem_table.rank in
(
select ceil((count(1) + 1) / 2) from table_name
union all
select floor((count(1) + 1) / 2) from table_name
)
--1.通过row_number()over()函数将原表score列按数据大小进行升序排列并给对应数据添加序号,形成rank列;
--2.根据中位数的定义,用count()求出数据总个数即数据排序后的最大编号,利用ceil()和floor()获取总数加一除以二后的向上和向下整数(结果能除尽,则向上向下取整皆为其本身),此步可定位中位数位置所在,再将对应向上和向下整数位置对应的score求均值即为中位数;
--3.where子查询中是一张一列两行的数据表,数据正是中位数前后的位置号;
本文为个人工作、学习所得,内容会持续更新。如有问题,欢迎交流指正~