date: 2019-03-22 17:02:37

updated: 2020-04-08 16:00:00

Hive Sql的日常使用笔记

1. distinct 和 group by

distinct 只能返回去重的列

group by 理论上是需要在 select 后面配合聚合函数(sum, avg, max, min, count)来使用的

select 后面没有在聚合函数中的列都需要写在 group by 的后面,eg:

select A1, A2, A3, max(B) from test group by A1, A2, A3

select distinct(A), B from testselect distinct A, B from test 返回的是一样的,返回的都是 A 和 B 的组合值没有重复的结果

如果需要去重的话,select 需要的列 from A, (select min(主键) from A group by 要去重的列)B where A.主键 = B.主键

2. left join

A left join B on A.a1 = B.b and A.a2 = 'val' 保留 A 的所有结果,同时 on 后面的结果只针对这一条 left join 语句,不会影响最后的筛选,所以如果要保留所有 A.a2 = 'val' 的数据的话,应该在最后写 where A.a2 = 'val'

3. if 和 case when

一层: if(A.a = 'key', val1, val2)

两层: if(A.a = 'key1', val1, if(A.a = 'key2', val2, val3))

case A.a
when 'key1' then 'val1'
when 'key2' then 'val2'
else 'val3'
end

4. regexp_replace

替换掉 A.a 字段中的点 regexp_replace(A.a, "\\.", "")

5. cast

cast(A.a as int)

6. concat

concat(A.a,'-01-01')

7. concat_ws 行转列

concat_ws('/', collect_set(label_name))label_name group by key

concat 会自动把参数转换为字符串进行拼接,但是 concat_ws 需要提前将数值 cast 成字符串

8. regexp

where trim(A.a) regexp '^[1-9 | A-E]'

9. from_unixtime

from_unixtime(unix_timestamp(),'yyyy-MM-dd hh:mm:ss') update_time

10. 索引

索引基数: 数据列所包含的不同值的数量。索引的基数相对于数据表行数较高(即列中包含很多不同的值,重复的值很少),这个时候创建的索引效果更好。因为查询优化器如果发现某个值出现在表的数据行中的百分比很高的时候,可能会忽略索引直接进行全盘扫描。

11. row_number()

row_number() over(partition by 主键 order by 字段1 desc)as r

12.多个条件

if(boolean, res1, if(boolean, res2, if(boolean, res3,……)))

13.nvl

nvl(a,b) 如果a为null 那就取b 只能判断null 不能判断空

14.decimal

cast(round((sum(an) * 100 / sum(tn)),2) as decimal(20,2))

round((sum(an) * 100 / sum(tn)),2) 可能会出现 84.6599999999 的数据,可能只是 hue 上的 bug,需要再处理一下

15.补零

if(substr(bp, 1, 1) != 'X' and bp is not null and trim(bp) != 'null' and trim(bp) != '' and trim(bp) != '*', lpad(bp, 10, '0'), bp)as temp

16.推数编码出错

Incorrect string value: '\xF0\xAF\xA0\xA5' for column 'customer_txt' at row 45

以下几种方法有可能可以解决:

  1. 修改字符集为 utf8mb4
  2. --default-character-set gbk 在 sqoop 最后转换为 gbk 编码
  3. 出错原因是 can't parse data ' ' 之类的话,可能是因为特殊字符,需要一个个排查,可以试一下 regexp_replace(field,'\0','')

17.去重

select distinct t1.objnr
from jest t1
where t1.stat = 'I0002'
and t1.objnr not in (select distinct objnr from jest where stat = 'I0076'); ==> select * from
(select objnr, min(if(stat = 'I0002', 0, 1))a, max(if(stat = 'I0076', 1, 0))b
from jest group by objnr)t where t.a = 0 and t.b = 1;

18.插入数据

insert into table values ('05:00','6') ,('06:00','7'),
('07:00','8'), ('08:00','9'), ('09:00','10'), ('10:00','11'), ('11:00','12'), ('12:00','13'),
('13:00','14');

19.每隔N小时取数分组求和

通过截取字符串,获取时间,除以N保留整数位,分组

20.正则表达式的匹配

select regexp_replace('[3]','[','a')	不识别
select regexp_replace('[3]','\[','a') 不识别
select regexp_replace('[3]','\\[','a') 识别
select regexp_replace('[3]',']','a') 识别
select regexp_replace('[3]','\]','a') 识别
select regexp_replace('[3]','\\]','a') 识别
select regexp_replace('[3,.]',',','a') 识别
select regexp_replace('[3,.]','.','a') aaaaa .会识别为通配符,即所有字符
select regexp_replace('[3,.]','\.','a') 不识别
select regexp_replace('[3,.]','\\.','a') [3,a] 识别

21.空字符串关联

  1. (NULL) 在 join on 的时候不会被关联出来
  2. '' ' ' 在 join on 的时候会相互关联,只要有匹配项就会关联出来
  3. (NULL) 只在 left jion 的时候可以出来

22.lateral view explode 列转行

select gid, assist
from origin_ennenergy_intelligent_operation.wo_baseinfo
lateral view explode
(split(split(split(regexp_replace(assist_man, '"',""), "\\[")[1],"\\]")[0], ",")) aa as assist

23. userids 包含 gid

find_in_set(gid, userids)  # userids 需要用逗号分隔
instr(userids, gid) 会让 ('2,11', '1') 也被筛选出来

24.pmod(a, b) 取模(取余)运算

pmod(7, 4) -> 3
pmod(9, -4) -> -3
# 9 mod -4 商可以取 -2 或 -3,因为 -3 < -2,所以商取 -3,-4 * -3 = 12, 9 - 12 = -3,所以最终结果是 -3
pmod(-9, 4) -> 3
# -9 mod 4 商可以取 -2 或 -3,因为 -3 < -2,所以商取 -3,4 * -3 = -12, -9 - (-12) = 3,所以最终结果是 3

25.insert 和 insert overwrite

insert overwrite 本质是先覆盖原先的表,再把新的数据插入

26.insert 和 insert into

insert table user(id, name) values(1, 'zhangsan');

insert into table user values(1, 'zhangsan');

27.max(if) 或者 max(case when) 行转列

select id,
max(if(name = 'buss', pass, '')) as buss,
max(if(name = 'record', pass, '')) as record,
max(if(name = 'stock', pass, '')) as stock,
max(if(name = 'client', pass, '')) as client
from test0610
group by id; select id,
MAX(CASE WHEN name = 'buss' THEN pass END) AS buss,
MAX(CASE WHEN name = 'record' THEN pass END) AS record,
MAX(CASE WHEN name = 'stock' THEN pass END) AS stock,
MAX(CASE WHEN name = 'client' THEN pass END) AS client
from test0610
group by id;

28.复制表结构 但不复制数据

create table Test2 like Test1;

29.两个限制条件

要让每一条数据都满足 balance < 0,gas > 0,转换成 count(if(balance >= 0, 1, 0)) as a, count(if(gas <= 0, 1, 0)) as b,然后 where 中取 a = 0 and b = 0 的数据

30.join优化

  1. 多表join,其中有一个是最大的表
select /*+ STREAMTABLE(table1) */ tabl1.a, table1.b, table2.c
from table1 join table2 on ......

hive会假定查询中最后一个表是最大的表。在对每行记录进行连接操作的时候,会尝试将其他表缓存起来,然后扫描最后那个表进行计算。通过 /*+ STREAMTABLE(table1) */ 可以显式地指出最大的表是哪一个,hive会将其作为驱动表,哪怕它不是在 join 的最后面

  1. 多表join,其中有一个是最小的表
select /*+ MAPJOIN(table1) */ tabl1.a, table1.b, table2.c
from table1 join table2 on ......

如果所有表中只有一张表是小表,那么可以在最大的表通过mapper的时候将小表完全放到内存中。Hive可以在map端执行连接过程(称为map-side JOIN),这是因为hive可以和内存中的小表进行逐一匹配,从而省略掉常规连接操作所需要的reduce过程。

31.导出mysql数据库的注释

SELECT
COLUMN_NAME 列名,
COLUMN_TYPE 数据类型,
DATA_TYPE 字段类型,
CHARACTER_MAXIMUM_LENGTH 长度,
IS_NULLABLE 是否为空,
COLUMN_DEFAULT 默认值,
COLUMN_COMMENT 备注
FROM
INFORMATION_SCHEMA.COLUMNS
table_schema = '库名'
AND
-- 如果不写的话,默认会查询出所有表中的数据,这样可能就分不清到底哪些字段是哪张表中的了,所以还是建议写上要导出的名名称
table_name = '表名'

32. count()

count(*):所有行进行统计,包括NULL行
count(1):所有行进行统计,包括NULL行
count(column):统计column所有非NULL行

33. sum(if...) 和 count(if...)

在计数的时候,以下两种方式是等效的:

sum(if(条件判断, 1, 0))

count(if(条件判断, 字段, NULL))

原因在于 NULL 并不参加任何计算(但是升序排序的时候 NULL 是第一个,因为ASC码最小)。

34. sum() over(...)

sum() over(partition by year) 计算结果是按照 year 分组来 sum 的总和
sum() over(partition by year order by month) 计算结果是按照 year 分组,1月算的是1月的和,2月算的是 1 - 2月的和, 3月算的是 1 - 3月的和

同理适用于其他的窗口函数

35. count(distinct a) 不支持窗口函数,即不支持后面跟着 over(partiton by 1)

36. size 函数 返回后面map或者array里面的元素个数

size(collect_set(字段)) over(partiton by 1)

37. 设置变量

set myvar = "test";
select ${hiveconf:myvar}

38. coalesce() 函数

依次查看每一个表达式,返回第一个非空值,如果都是空,最后返回空值

coalesce(expression_1, expression_2, ...,expression_n)

39. count(distinct) 优化

直接使用 count(distinct) 会把数据放入到一个 reducer 下进行计算,导致运行缓慢。

比如统计本月活跃用户个数

优化一:

-- 外层SELECT求和
SELECT
SUM(mau_part) mau
FROM
(
-- 内层SELECT分别进行COUNT(DISTINCT)计算
SELECT
substr(uuid, 1, 3) uuid_part,
COUNT(DISTINCT substr(uuid, 4)) AS mau_part
FROM detail_sdk_session
WHERE partition_date >= '2020-01-01' AND partition_date <= nowdate
GROUP BY substr(uuid, 1, 3)
) t; ∵ uuid 是唯一的 ∴ 最后的结果 每个uuid_part对应的mau_part都是1,最后求和就是用户总数 这个写法的好处是,利用 group by 将数据分散到不用的 reducer 进行 count(distinct)计算,提高查询效率

这里 uuid 只截取了3位,如果截取位数过多,假设 uuid 长度为30位,内层 group by 会产生 30^n 个分组,那么外层也需要进行 30^n 次求和

优化二:

--  第三层SELECT
SELECT
SUM(s.mau_part) mau
FROM
(
-- 第二层SELECT
SELECT
tag,
COUNT(*) mau_part
FROM
(
-- 第一层SELECT
SELECT
uuid,
CAST(RAND() * 100 AS BIGINT) tag -- 为去重后的uuid打上标记,标记为:0-100之间的整数。
FROM detail_sdk_session
WHERE partition_date >= '2020-01-01'
AND partition_date <= nowdate
AND uuid IS NOT NULL
GROUP BY uuid -- 通过GROUP BY,保证去重
)t
GROUP BY tag
)s; 第一层SELECT:对uuid进行去重,并为去重后的uuid打上整数标记
第二层SELECT:按照标记进行分组,统计每个分组下uuid的个数
第三层SELECT:对所有分组进行求和

如果数据量确实很大,也可以增加分组的个数。例如:CAST(RAND() * 1000 AS BIGINT) tag

Hive Sql的日常使用笔记的更多相关文章

  1. Hive sql & Spark sql笔记

    记录了日常使用时遇到的特殊的查询语句.不断更新- 1. SQL查出内容输出到文件 hive -e "...Hive SQL..." > /tmp/out sparkhive ...

  2. SQL反模式学习笔记9 元数据分裂

    目标:支持可扩展性.优化数据库的结构来提升查询的性能以及支持表的平滑扩展. 反模式:克隆表与克隆列 1.将一张很长的表拆分成多张较小的表,使用表中某一个特定的数据字段来给这些拆分出来的表命名. 2.将 ...

  3. Android:日常学习笔记(9)———探究持久化技术

    Android:日常学习笔记(9)———探究持久化技术 引入持久化技术 什么是持久化技术 持久化技术就是指将那些内存中的瞬时数据保存到存储设备中,保证即使在手机或电脑关机的情况下,这些数据仍然不会丢失 ...

  4. Android:日常学习笔记(10)———使用LitePal操作数据库

    Android:日常学习笔记(10)———使用LitePal操作数据库 引入LitePal 什么是LitePal LitePal是一款开源的Android数据库框架,采用了对象关系映射(ORM)的模式 ...

  5. SQL Server技术内幕笔记合集

    SQL Server技术内幕笔记合集 发这一篇文章主要是方便大家找到我的笔记入口,方便大家o(∩_∩)o Microsoft SQL Server 6.5 技术内幕 笔记http://www.cnbl ...

  6. 【hive】——Hive sql语法详解

    Hive 是基于Hadoop 构建的一套数据仓库分析系统,它提供了丰富的SQL查询方式来分析存储在Hadoop 分布式文件系统中的数据,可以将结构 化的数据文件映射为一张数据库表,并提供完整的SQL查 ...

  7. SQL Server 2012 数据库笔记

    慕课网 首页 实战 路径 猿问 手记     Python 手记 \ SQL Server 2012 数据库笔记 SQL Server 2012 数据库笔记 2016-10-25 16:29:33 1 ...

  8. Hive SQL 监控系统 - Hive Falcon

    1.概述 在开发工作当中,提交 Hadoop 任务,任务的运行详情,这是我们所关心的,当业务并不复杂的时候,我们可以使用 Hadoop 提供的命令工具去管理 YARN 中的任务.在编写 Hive SQ ...

  9. hive sql 语法详解

    Hive 是基于Hadoop 构建的一套数据仓库分析系统,它提供了丰富的SQL查询方式来分析存储在Hadoop 分布式文件系统中的数据,可以将结构 化的数据文件映射为一张数据库表,并提供完整的SQL查 ...

随机推荐

  1. PyCharm专业版编辑器安装(含破解步骤)

    一.首先下载好安装包: 二.安装步骤: 1.双击安装包,打开安装界面,点击"next": 2.选择安装路径,点击"next": 3.电脑是64位的就勾选64-b ...

  2. 俯瞰 Java 服务端开发

    原文首发于 github ,欢迎 star . Java 服务端开发是一个非常宽广的领域,要概括其全貌,即使是几本书也讲不完,该文将会提到许多的技术及工具,但不会深入去讲解,旨在以一个俯瞰的视角去探寻 ...

  3. cookie、session和md5加密

    cookie Http无状态协议,只能在同一个网站(包括多个页面)下获取,存储在客户端本地的一段信息,帮助我们存储信息获取信息.但是同样有风险:我们自己在浏览器上可以操作或者设置Cookie. con ...

  4. MySQL 5.7安装与配置

    Windows 一.到MySQL官网下载压缩版本,下载后文件为mysql-5.7.20-winx64.zip,解压到D:\develop\mysql-5.7.20-winx64.   二.在系统变量P ...

  5. Java面试题之计算字符/字符串出现的次数

    一.计算字符在给定字符串中出现的次数 二.计算字符串在给定字符串中出现的次数 1 import java.util.HashMap; 2 import java.util.Map; 3 4 publi ...

  6. Python-IndentationError: expected an indented block

    Error: IndentationError: expected an indented block Where? Python代码执行时候报这个错误 Why? Python代码具有严格缩进规范,默 ...

  7. 模型集成model ensemble

    A prediction model that is composed of a set of models is called a model ensemble. Baggging 和Boostin ...

  8. 082 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 01 构造方法-无参构造方法

    082 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 01 构造方法-无参构造方法 本文知识点:构造方法-无参构造方法 说明:因为时间紧张, ...

  9. 【题解】SAC E#1 - 一道难题 Tree

    Problem is here \(\text{Solution:}\) 首先,一眼看出这是最小割,只要叶子节点对汇点\(T\)连接流量为\(inf\)的边就可以一遍最大流搞定了. 剩下的问题在于,如 ...

  10. 连接mysql客户端报错: java.sql.SQLException: Unable to load authentication plugin 'caching_sha2_password'

    报这个错可能是因为用了低版本的的客户端.驱动连接高版本的mysql服务器. 解决方式有三种:升级客户端版本.修改服务端认证方式和适应服务端认证方式. 我是通过升级客户端版本解决,参考一下链接: Upg ...