Hive sql使用小结

1.首先,很多时我们需要在Hive中去重数据:(语法和Oracle中的去重很类似,子查询更名为 t 这个不能省略)

select  ID, CASE_ID_
from (
 SELECT 
 ID, CASE_ID_ , row_number() OVER(PARTITION BY CASE_ID_ ) as row_flg   

 FROM table

)t where t.row_flg=1 

2.对某一个存储手机号码的zidu字段进行过滤区号可以这样(记得是\\+86 而不是 +86,+属于特殊字符):

 SELECT  ID, CASE_ID_, 
 regexp_replace(regexp_replace(regexp_replace(regexp_replace(TO_ACCOUNT_,'\\+86', ''),'\\+85', ''),'-', ''),' ', '') AS TO_ACCOUNT_

 FROM table

当然,使用正则去掉会更好:

 SELECT  ID, CASE_ID_, 
 regexp_replace(regexp_replace(regexp_replace(TO_ACCOUNT_,'(\\+\\d{2})?', ''),'-', ''),' ', '') AS TO_ACCOUNT_

 FROM table

-- 参考:(去除区号) https://blog.youkuaiyun.com/wmx690/article/details/80354321
-- (去除http url) https://blog.youkuaiyun.com/abauch_d/article/details/7837089
-- 注:去除url那个正则不太全面,只能去除 http://ip,端口号之后的内容不能去除

3. 对于某一个存储可能会有 \t \s 等字符的字段,可以这样过滤:

 SELECT  ID, CASE_ID_, 
 regexp_replace(CONTENT, '\\s+', '')
 FROM table

4.对于某两个字段是互补的情况可以这样:

 SELECT  ID, CASE_ID_, 
  CASE WHEN TIME like '20___%__%_ %_:%_:%_' THEN TIME_ ELSE TIME1 END,
 FROM table

-- 如果要拼接字段的值到like条件可以这样
select * from table where update_time like concat('%',TIME,'%');

5 创建表可以这样:

-- hive表

CREATE TABLE test(
APP_ID_ STRING,
CASE_ID_ STRING
)ROW FORMAT DELIMITED fields terminated BY '\t' NULL DEFINED AS '' STORED AS TEXTFILE;

-- 或者

CREATE TABLE test(
 APP_ID_ STRING,
 CASE_ID_ STRING
)
 ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
 WITH SERDEPROPERTIES ("separatorChar" = "\t", "quoteChar" = "'", "escapeChar" = "\\" )
 STORED AS TEXTFILE;

-- 或者
CREATE TABLE test
ROW FORMAT DELIMITED fields terminated BY '\t' NULL DEFINED AS '' STORED AS TEXTFILE
as select * from other_table;


-- ES映射表 (要先把elasticsearch-hadoop-5.5.0.jar加入到hive的辅助包路径)
CREATE TABLE test(
 APP_ID_ STRING,
 CASE_ID_ STRING
 )
STORED BY 'org.elasticsearch.hadoop.hive.EsStorageHandler' 
TBLPROPERTIES (
  'es.nodes'='node01,node02', 
  'es.port'='9200', 
  'es.resource'='index/mapping'
 );

-- 下载jar:https://www.elastic.co/downloads/past-releases/elasticsearch-apache-hadoop-5-5-0

6.当某一个字段的值以某一个字符 如: ";" ,我们想取出 ";" 前的内容可以进行切割字符串:

 SELECT  ID, CASE_ID_, 
 split('192.168.0.1','\\.')
 FROM table

-- 当split包含在 "" 之中时 需要加4个\,如 hive -e "....  split('192.168.0.1','\\\\.') ... "  不然得到的值是null

 7.如6所说的,当我们使用 hive -e "..." 并且在java代码中执行hive sql的时候,原本是\\ 的要写成 \\\\ ,不然会报错,而 sql语句中的引号最好用单引号 ' 

参考:https://blog.youkuaiyun.com/lsr40/article/details/81566424

8.文件从某一个节点下load到hive(比如csv放到node01节点的/opt/csv目录下):

 load data local inpath '/opt/csv/csv_201812261002.csv'
 into table schemaName.tableName

9.文件从hdfs上到hive:

load data inpath 'hdfs://node01:8020/bulkload'
 into table test;

-- 以下是覆盖原有的表数据
load data inpath 'hdfs://node01:8020/bulkload' overwrite
 into table test;

10.hive导出到节点本地路径:

 insert overwrite local directory '/home/temp'
 row format delimited
 fields terminated by '\t'
 select * from tablename;

11.hive导出到hdfs:

 insert overwrite directory '/home/temp'
 row format delimited
 fields terminated by '\t'
 select * from tablename;


-- 可能遇到 hive表中字段显示为NULL时,HDFS文件中存储为\N 这种情况 , 可以像下面这样属性设置
insert overwrite directory '/home/temp'
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
WITH SERDEPROPERTIES (
'field.delim'='\t',
'serialization.format'= '',
'serialization.null.format'=''  
) STORED AS TEXTFILE
select * from tablename;

-- 或者在创建hive表时指定 ROW FORMAT DELIMITED NULL DEFINED AS ''
create table tableName( id string, name string)row format delimited fields terminated by '\t' NULL DEFINED AS '' stored as textfile;

-- 或者直接修改表定义
alter table tableNameset serdeproperties('serialization.null.format' = '');

 

:创建ES的index以及mapping:

-- 可以使用postman来创建es的index和mapping

http://192.168.0.1:9200/indexName
{
   "setting":{
             "number_of_shards":5,
             "number_of_replicas":1
   }
}


http://192.168.0.1:9200/indexName/mappingName/_mapping

{
     "properties": {
           "field1": {
                    "index": "not_analyzed",
                    "type": "string"
           },
           "field2": {
                    "index": "not_analyzed",
                    "type": "string"
           },
           "field3": {
                    "index": "not_analyzed",
                    "type": "string"
           },
           "field4": {
                    "index": "not_analyzed",
                    "type": "string"
           }
     }
}


-- Hive表数据插入ES
-- 先创建ES映射表,然后将Hive表数据insert到ES映射表,这样ES就会插入数据了,ES的mapping会自动创建

insert OVERWRITE table es_table
SELECT * FROM hive_table;

11. 具体参考 Hive sql 的 官网api :http://trafodion.apache.org/docs/sql_reference/#examples_of_substring

12.设置Hive查询引擎,set hive.execution.engine=mr ;

 

1. 在where中判断date不为空的时候要注意 date is not null 和 date != null 的区别。

2. select中统计百分比的时候,要注意分母(总数)不能为0的情况。

<think>我们正在讨论Hive SQL中UNION ALL的使用方法和注意事项。根据用户提供的引用内容,我们可以总结如下: 1. 引用[1]和[2]指出,UNION ALL用于合并多个查询的结果集,不会去重,而UNION会去重。在性能上,UNION ALL优于UNION,因为不需要去重操作。 2. 引用[3]提到,在UNION ALL的各个子查询中,不能单独使用ORDER BY、CLUSTER BY、DISTRIBUTE BY、SORT BY、LIMIT等子句。如果需要排序或限制,可以将每个子查询用括号括起来,并在外部使用这些子句,或者使用WITH AS子句先处理再合并。 3. 引用[4]说明,UNION ALL的结果字段顺序以第一个查询的字段顺序为准,后续查询的结果会按字段顺序(而不是字段名)附加在后面。 4. 引用[5]虽然主要讲explode,但其中使用了UNION ALL来创建示例数据,展示了UNION ALL可以用来合并多个SELECT的结果。 因此,我们可以整理出Hive SQL使用UNION ALL的方法和注意事项: ### 使用方法 1. **基本语法**: ```sql SELECT col1, col2 FROM table1 UNION ALL SELECT col1, col2 FROM table2; ``` 2. **合并多个结果集**: ```sql SELECT ... FROM ... UNION ALL SELECT ... FROM ... UNION ALL SELECT ... FROM ...; ``` 3. **配合WITH AS(CTE)使用**:如果需要对每个子查询进行排序或限制,可以先将每个子查询定义为CTE,然后在UNION ALL中使用: ```sql WITH q1 AS ( SELECT col1, col2 FROM table1 ORDER BY col1 LIMIT 10 ), q2 AS ( SELECT col1, col2 FROM table2 ORDER BY col2 LIMIT 20 ) SELECT * FROM q1 UNION ALL SELECT * FROM q2; ``` ### 注意事项 1. **字段顺序和数量**: - 每个SELECT语句必须有相同数量的列。 - 列的数据类型必须兼容(Hive会尝试隐式转换,但最好显式转换确保一致)。 - 结果集的字段名以第一个SELECT语句的字段名为准,后续SELECT语句的字段名可以不同(但实际数据按位置合并)。 2. **排序和限制**: - 在UNION ALL的每个子查询中,不能直接使用ORDER BY、CLUSTER BY、DISTRIBUTE BY、SORT BY、LIMIT(除非用子查询括起来,或者使用CTE)[^3]。 - 如果需要对整个结果排序或限制,可以在UNION ALL之后使用: ```sql SELECT * FROM ( SELECT ... FROM ... UNION ALL SELECT ... FROM ... ) combined_result ORDER BY col1 LIMIT 100; ``` 3. **性能考虑**: - 尽量使用UNION ALL而不是UNION,除非需要去重,因为UNION ALL避免了去重操作,性能更好[^2]。 - 如果数据量很大,可以考虑在子查询中预先过滤数据以减少数据量。 4. **空值与NULL处理**: - 如果某个列在所有SELECT语句中并不都存在,可以使用NULL或常量值填充,以保持列数一致。例如: ```sql SELECT col1, col2 FROM table1 UNION ALL SELECT col1, NULL AS col2 FROM table2; -- 假设table2没有col2,用NULL填充 ``` 5. **嵌套UNION ALL**: - 如果需要复杂的合并,可以使用嵌套查询,但要注意可读性。 ### 示例 #### 示例1:合并两个表的数据(不去重) ```sql SELECT user_id, order_date, amount FROM orders_2023 UNION ALL SELECT user_id, order_date, amount FROM orders_2022; ``` #### 示例2:使用CTE预先处理子查询 ```sql WITH orders_2023_top AS ( SELECT user_id, SUM(amount) AS total_amount FROM orders_2023 GROUP BY user_id ORDER BY total_amount DESC LIMIT 100 ), orders_2022_top AS ( SELECT user_id, SUM(amount) AS total_amount FROM orders_2022 GROUP BY user_id ORDER BY total_amount DESC LIMIT 100 ) SELECT * FROM orders_2023_top UNION ALL SELECT * FROM orders_2022_top; ``` #### 示例3:字段顺序匹配(字段名不同但顺序相同) ```sql -- table1有字段a, b;table2有字段x, y,但类型与a, b分别相同 SELECT a AS col1, b AS col2 FROM table1 UNION ALL SELECT x, y FROM table2; -- 这里字段名无关紧要,按位置合并到col1和col2 ``` ### 常见错误 1. **字段数量不一致**: ```sql -- 错误:第一个查询有两列,第二个查询有三列 SELECT col1, col2 FROM table1 UNION ALL SELECT col1, col2, col3 FROM table2; ``` 2. **在子查询中直接使用ORDER BY(未用括号或CTE)**: ```sql -- 错误写法(会报错) SELECT col1 FROM table1 ORDER BY col1 UNION ALL SELECT col1 FROM table2; -- 正确写法:用子查询包裹 SELECT * FROM (SELECT col1 FROM table1 ORDER BY col1) t1 UNION ALL SELECT * FROM table2; ``` 3. **数据类型不兼容**: ```sql -- 错误:第一个查询col1是字符串,第二个查询col1是整数 SELECT name AS col1 FROM users UNION ALL SELECT age AS col1 FROM orders; -- 类型不匹配 ``` ### 总结 使用UNION ALL时,关键点在于保证每个子查询的列数相同、数据类型兼容,并注意排序和限制的使用方式。通过合理使用CTE和子查询,可以构建复杂的合并查询。同时,由于UNION ALL不会去重,效率较高,在不需要去重时应优先使用。 --- §§相关问题§§ 1. Hive SQL中UNION和UNION ALL在性能上有何差异? 2. 如何在Hive中对UNION ALL后的结果进行全局排序? 3. Hive中UNION ALL操作是否会影响数据分布的优化? </think>### Hive SQL 中 UNION ALL 的使用方法与注意事项 #### ️ **基本语法** ```sql SELECT 列1, 列2... FROM 表A UNION ALL SELECT 列1, 列2... FROM 表B; ``` #### 📌 **核心注意事项** 1. **字段顺序优先于字段名匹配** - 结果集按第一个查询的字段顺序对齐 - 字段名不同不影响合并(位置匹配) ```sql -- 表A: (id, name) | 表B: (user_id, user_name) SELECT id, name FROM A UNION ALL SELECT user_id, user_name FROM B; -- 正确:按字段顺序合并 ``` > 结果字段名为 `id, name`(取自第一个 SELECT)[^4] 2. **排序/分页的特殊处理** - 不能在子查询中单独使用 `ORDER BY/LIMIT` - 必须通过子查询或 CTE 包裹排序逻辑: ```sql WITH dataset1 AS ( SELECT * FROM A ORDER BY create_time LIMIT 100 ), dataset2 AS ( SELECT * FROM B ORDER BY update_time LIMIT 50 ) SELECT * FROM dataset1 UNION ALL SELECT * FROM dataset2; -- 正确写法[^3] ``` 3. **数据类型兼容性** - 对应字段的数据类型必须隐式兼容 - 显式转换避免错误: ```sql SELECT string_col, int_col FROM A UNION ALL SELECT cast(double_col AS STRING), cast(float_col AS INT) FROM B; ``` 4. **性能优化要点** - 优先用 `UNION ALL` 替代 `UNION`(避免去重开销)[^2] - 在子查询中预先过滤数据: ```sql SELECT * FROM ( SELECT * FROM logs WHERE dt='2023-10-01' -- 分区过滤 ) filtered UNION ALL ... ``` 5. **NULL 值处理** - 使用 `COALESCE` 统一空值表示: ```sql SELECT COALESCE(name,'N/A') FROM users UNION ALL SELECT COALESCE(nickname,'N/A') FROM profiles ``` #### ️ **典型错误场景** 1. **字段数量不匹配** ```sql SELECT col1, col2 FROM A UNION ALL SELECT col1 FROM B; -- 错误:列数不一致 ``` 2. **错误使用排序** ```sql SELECT * FROM A ORDER BY col1 -- 错误:直接ORDER BY UNION ALL SELECT * FROM B; ``` 3. **忽略数据类型** ```sql SELECT string_col FROM A UNION ALL SELECT timestamp_col FROM B; -- 错误:类型不兼容 ``` #### ✅ **最佳实践示例** ```sql WITH current_month AS ( SELECT user_id, SUM(amount) AS total FROM orders WHERE dt BETWEEN '2023-10-01' AND '2023-10-31' GROUP BY user_id ), last_month AS ( SELECT user_id, SUM(amount) AS total FROM orders WHERE dt BETWEEN '2023-09-01' AND '2023-09-30' GROUP BY user_id ) SELECT 'current' AS period, user_id, total FROM current_month UNION ALL SELECT 'last' AS period, user_id, total FROM last_month; ``` > 该方案: > 1. 使用 CTE 预聚合数据 > 2. 添加标识字段区分来源 > 3. 显式统一输出结构 > 4. 利用分区过滤提高性能[^1][^2] ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值