Skip to content

第 4 章 广电用户基本信息简单查询 ​

写给新手的开篇 ​

本章是 Hive SQL 的入门核心,承接第 3 章的建表与数据导入,教你从广电用户基本信息表中,精准、高效地拿出想要的数据,是后续所有用户分析、消费统计、行为洞察的基础。

学完本章,你能独立完成 80% 的广电用户基础分析需求:

  1. 精准查询指定用户的编号、开户时间、状态等核心信息
  2. 筛选出销户、正常等指定状态的用户清单
  3. 统计品牌数量、用户等级分布、各状态用户数等核心指标
  4. 对用户数据进行分组、排序、分页,快速定位 TOP 级数据
  5. 用正则表达式快速匹配字段,简化复杂查询

前置准备:已完成第 3 章的ZJSM业务库创建、mediamatch_usermsg用户基本表创建、CSV 数据导入,能正常进入 Hive 客户端并切换到ZJSM库。

核心业务表字段回顾:本章所有案例均基于mediamatch_usermsg表,核心字段如下

表格

字段名业务含义
phone_no用户编号(唯一主键,核心关联字段)
open_time用户开户时间
run_name用户状态(正常、主动销户、被动销户等)
sm_name品牌名称
owner_name用户等级名称
run_time用户状态变更时间
sm_code品牌编号
owner_code用户等级编号
addressoj用户完整地址
terminal_no用户地址编号
force宽带是否生效

前置必执行配置(新手必开,提升查询体验)

hive
-- 切换到广电业务库
USE ZJSM;
-- 开启查询结果列名显示
SET hive.cli.print.header = true;
-- 列名仅显示字段名,不显示表名
SET hive.resultset.use.unique.column.names=false;
-- 开启提示符显示当前数据库,避免建表/查询走错库
SET hive.cli.print.current.db=true;

一、模块一:SELECT 基础查询(所有查询的根基) ​

1. 大白话理解 ​

SELECT...FROM是 Hive 查询最核心的语法,一句话解释:SELECT后面写你想要看的字段,FROM后面写数据来自哪张表。

2. 核心语法 ​

hive
SELECT [ALL | DISTINCT] 字段1, 字段2, 表达式/函数...
FROM 表名 [AS 表别名];

3. 分点详解 + 入门案例 ​

(1)基础字段查询 ​

只查询你需要的字段,是生产环境的最佳实践,避免全表扫描浪费性能。

入门案例(任务 4.1):查询广电用户的用户编号及开户时间

hive
-- 代码4-4 精准查询指定字段
SELECT phone_no, open_time 
FROM mediamatch_usermsg;

-- 加LIMIT限制返回条数,新手测试必加,避免全量数据刷屏
SELECT phone_no, open_time 
FROM mediamatch_usermsg
LIMIT 10;

(2)*通配符的使用与禁忌 ​

*代表表中所有字段,新手测试时可以用,但生产环境严禁滥用。

hive
-- 代码4-2 查询表中所有字段
SELECT * 
FROM mediamatch_usermsg
LIMIT 5;

✅ 新手避坑:

  • 生产环境用*会扫描全表所有字段,大数据量下会造成严重的性能浪费,甚至任务卡死
  • 仅在测试表结构、验证数据是否导入成功时使用,业务查询必须精准指定字段

(3)表别名的使用 ​

给表起一个简短的别名,能简化 SQL 书写,尤其后续多表关联查询时必备。

hive
-- 代码4-3 表别名使用示例
SELECT t.phone_no, t.open_time, t.run_name
FROM mediamatch_usermsg AS t -- AS关键字可省略,直接写mediamatch_usermsg t
LIMIT 10;

✅ 新手避坑:

  • 表别名不能用 Hive 关键字,否则会语法报错
  • 中文别名必须用反单引号包裹,比如FROM mediamatch_usermsg AS 用户表
  • 表别名不会影响查询性能,仅为了提升 SQL 可读性

二、模块二:WHERE 条件过滤(精准筛选数据) ​

1. 大白话理解 ​

SELECT...FROM会返回全表数据,而WHERE关键字就是给查询加一道「过滤网」,只留下符合你要求的数据,是提升查询效率、精准定位数据的核心。

2. 核心语法 ​

hive
SELECT 字段1,字段2...
FROM 表名
WHERE 过滤条件;
  • 过滤条件可以是一个或多个,多个条件用AND/OR连接
  • 只有满足条件、返回结果为TRUE的数据,才会被保留到最终结果中

3. 6 种常用过滤条件 + 广电业务案例 ​

(1)关系运算符过滤 ​

最基础的等值、大小比较,适用于数值、字符串的精准匹配。

表格

运算符含义
=相等匹配
!=/<>不相等匹配
>/<大于 / 小于
>=/<=大于等于 / 小于等于

入门案例:查询指定用户编号的用户信息

hive
-- 代码4-5 等值匹配查询
SELECT phone_no, open_time, run_name
FROM mediamatch_usermsg
WHERE phone_no = '2032485';

(2)IN 关键字:集合匹配 ​

判断字段值是否在指定的集合中,替代多个OR等值条件,简化 SQL。

hive
-- 代码4-6 IN关键字查询多个指定用户
SELECT phone_no, open_time, run_name
FROM mediamatch_usermsg
WHERE phone_no IN ('2116612','2017186','2017187','2082337');

-- 反向匹配:NOT IN,查询不在集合中的用户
SELECT phone_no, open_time, run_name
FROM mediamatch_usermsg
WHERE phone_no NOT IN ('2116612','2017186');

(3)BETWEEN AND:区间匹配 ​

判断字段值是否在指定闭区间内,适用于数值、日期的范围筛选。

hive
-- 代码4-7 查询用户编号在指定区间内的用户
SELECT phone_no, open_time
FROM mediamatch_usermsg
WHERE phone_no BETWEEN '2032485' AND '2032500';

✅ 新手避坑:

  • BETWEEN AND是闭区间,包含起始值和结束值
  • 必须保证值1 < 值2,否则区间无效,查询不到任何数据

(4)NULL 关键字:空值判断 ​

专门用来判断字段是否为空值,注意空值和 0、空字符串有本质区别。

hive
-- 代码4-8 查询用户编号不为空的有效用户
SELECT phone_no 
FROM mediamatch_usermsg
WHERE phone_no IS NOT NULL;

-- 查询地址为空的用户
SELECT phone_no, addressoj
FROM mediamatch_usermsg
WHERE addressoj IS NULL;

✅ 新手避坑:

  • 绝对不能用字段 = NULL判断空值,Hive 中任何值和 NULL 做=比较,结果都是 NULL,会查不到数据
  • 正确写法只有IS NULL/IS NOT NULL

(5)LIKE 关键字:模糊匹配 ​

用来做文本的模糊查询,配合通配符实现灵活匹配,是业务中最常用的过滤方式。

  • 核心通配符:

    • %:匹配任意长度的字符串,包括空字符串
    • _:匹配单个字符

核心业务案例(任务 4.2):查询所有销户状态的用户

用户销户分为「主动销户」和「被动销户」,都以「销户」结尾,用%通配符完美匹配。

hive
-- 代码4-12 查询销户状态的用户基本信息
SELECT phone_no, run_name, open_time 
FROM mediamatch_usermsg
WHERE run_name LIKE '%销户';

-- 拓展:查询品牌名称以「宽频」结尾的用户
SELECT phone_no, sm_name 
FROM mediamatch_usermsg
WHERE sm_name LIKE '%宽频';

-- 拓展:_匹配单个字符,查询用户编号第2位是2,结尾是296756的用户
SELECT phone_no, sm_name 
FROM mediamatch_usermsg
WHERE phone_no LIKE '_296756';

(6)RLIKE 关键字:正则匹配 ​

比 LIKE 更强大的模糊匹配,支持正则表达式,适合复杂的文本匹配场景。

hive
-- 代码4-11 正则匹配品牌名称包含「珠江」或「甜果」的用户
SELECT phone_no, sm_name 
FROM mediamatch_usermsg
WHERE sm_name RLIKE '.*(珠江|甜果).*';

三、模块三:DISTINCT 去重 + 聚合函数(数据统计核心) ​

1. DISTINCT 关键字:去除重复数据 ​

大白话理解 ​

DISTINCT会过滤掉查询结果中的重复数据,只保留唯一值,适合统计种类、去重清单等场景。

核心语法 + 案例 ​

hive
-- 单字段去重:查询所有不重复的用户状态
SELECT DISTINCT run_name
FROM mediamatch_usermsg;

-- 代码4-13 多字段去重:只有用户状态+用户等级都相同时,才会被去重
SELECT DISTINCT run_name, owner_name 
FROM mediamatch_usermsg;

✅ 新手避坑:

  • DISTINCT必须放在所有字段的最前面,不能写在字段中间
  • 多字段去重时,只有所有字段的值都完全相同,才会被判定为重复数据

2. 聚合函数:数据统计计算 ​

聚合函数是对一组数据进行统计计算,最终返回一个统计结果,是业务指标统计的核心工具。

常用聚合函数 + 广电业务案例 ​

表格

函数核心作用广电业务场景
COUNT(*)/COUNT(1)统计总行数统计用户总数、各状态用户数
COUNT(DISTINCT 字段)统计去重后的行数统计品牌种类个数、不重复的用户等级数
MIN(字段)取字段最小值最早开户时间、最小用户编号
MAX(字段)取字段最大值最晚状态变更时间、最大用户编号
AVG(字段)取字段平均值平均开户时长(需配合日期函数)
SUM(字段)取字段值总和消费总额统计(后续账单表用)

核心业务案例(任务 4.3):统计用户基本信息表中品牌名称的种类个数

hive
-- 代码4-15 统计品牌名称种类(去重后计数)
SELECT COUNT(DISTINCT sm_name) AS brand_count
FROM mediamatch_usermsg;

-- 拓展:查询最小的用户编号
SELECT MIN(phone_no) 
FROM mediamatch_usermsg;

-- 拓展:统计所有有效用户总数
SELECT COUNT(*) AS user_total
FROM mediamatch_usermsg
WHERE phone_no IS NOT NULL;

四、模块四:列别名(让查询结果更易读) ​

1. 大白话理解 ​

给查询的字段、计算结果、聚合函数结果起一个新名字,尤其是把英文字段转成中文,让查询结果一目了然,不用再猜英文字段的含义。

2. 核心语法 ​

hive
SELECT 字段名 [AS] 列别名
FROM 表名;
  • AS关键字可省略,直接写字段名 别名即可
  • 中文别名必须用反单引号 `` 包裹

3. 入门配置 + 业务案例 ​

(1)前置配置:开启列名显示 ​

Hive CLI 默认不显示查询结果的列名,必须先执行以下配置开启:

hive
-- 代码4-16 开启查询结果列名显示
SET hive.cli.print.header = true;
-- 代码4-17 列名仅显示字段名,不显示表名前缀
SET hive.resultset.use.unique.column.names=false;

✅ 新手提示:以上配置仅当前会话有效,退出 Hive 客户端后重新登录需要重新执行;想永久生效,需要修改hive-site.xml配置文件。

(2)核心业务案例(任务 4.4):统计不同客户等级名称的数据记录数 ​

hive
-- 代码4-20 统计不同客户等级的用户数,设置中文列别名
SELECT 
  owner_name AS `客户等级名称`, 
  COUNT(*) AS `记录数`
FROM mediamatch_usermsg
GROUP BY owner_name;

-- 代码4-19 简单中文别名示例
SELECT sm_name AS `品牌名称` 
FROM mediamatch_usermsg 
LIMIT 5;

4. 新手必守规则 ​

  1. WHERE、GROUP BY、HAVING关键字中不能使用列别名,因为 Hive 执行顺序中,这些关键字先于SELECT执行,识别不到别名
  2. ORDER BY排序时,必须使用列别名,不能使用原始表达式
  3. 别名不能使用 Hive 关键字,中文别名必须用反单引号包裹

五、模块五:GROUP BY 分组查询(分类统计核心) ​

1. 大白话理解 ​

GROUP BY会把数据按指定的字段分成不同的组,比如按「用户状态」分组、按「用户等级」分组,然后对每个分组单独做聚合统计,实现「分类统计」的需求。

2. 核心语法 ​

hive
SELECT 分组字段, 聚合函数
FROM 表名
[WHERE 分组前过滤条件]
GROUP BY 分组字段1, 分组字段2...;

3. 核心铁则(新手必背,否则必报错) ​

SELECT关键字后面的字段,要么出现在 GROUP BY 的分组字段中,要么被聚合函数包裹,两者必须满足其一,否则会直接语法报错。

错误案例 vs 正确案例 ​

hive
-- 代码4-21 错误示例:SELECT里的phone_no既不在GROUP BY里,也没被聚合函数包裹,必报错
SELECT phone_no, run_name, sm_name 
FROM mediamatch_usermsg
GROUP BY run_name, sm_name;

-- 代码4-22 正确示例:SELECT里的字段和GROUP BY里的完全一致
SELECT run_name, sm_name 
FROM mediamatch_usermsg
GROUP BY run_name, sm_name;

-- 代码4-23 正确示例:非分组字段用聚合函数包裹
SELECT COUNT(phone_no) AS user_count, run_name, sm_name 
FROM mediamatch_usermsg
GROUP BY run_name, sm_name;

4. 核心业务案例(任务 4.5):统计不同用户状态的数据记录数 ​

hive
-- 代码4-24 按用户状态分组,统计每个状态的用户总数
SELECT 
  run_name AS `用户状态`,
  COUNT(*) AS `用户数`
FROM mediamatch_usermsg
GROUP BY run_name;

5. 新手避坑 ​

  • GROUP BY可以按多个字段分组,只有所有分组字段的值都相同时,才会被分到同一组
  • WHERE是分组前过滤,先过滤掉不符合条件的数据,再对剩下的数据分组,WHERE里不能用聚合函数

六、模块六:HAVING 关键字(分组结果过滤) ​

1. 大白话理解 ​

HAVING是对GROUP BY分组后的聚合结果进行过滤,专门解决「WHERE 里不能用聚合函数」的问题。

2. WHERE vs HAVING 核心区别(新手必懂) ​

表格

关键字过滤时机能否使用聚合函数适用场景
WHERE分组前过滤,先过滤再分组不能原始数据的行级过滤
HAVING分组后过滤,先分组再过滤必须配合聚合函数使用分组统计结果的过滤

3. 核心业务案例(任务 4.6):统计用户数量大于 200 的客户等级 ​

hive
-- 代码4-26 分组后筛选用户数大于200的客户等级
SELECT 
  owner_name AS `客户等级名称`,
  COUNT(*) AS `用户数`
FROM mediamatch_usermsg
GROUP BY owner_name
-- 对分组后的聚合结果过滤,只保留用户数>200的等级
HAVING COUNT(*) > 200;

-- 拓展:筛选用户数大于10000的用户状态
SELECT COUNT(*) AS nums, run_name 
FROM mediamatch_usermsg 
GROUP BY run_name
HAVING COUNT(*) > 10000;

七、模块七:排序 + LIMIT 分页(结果排序与条数限制) ​

1. 4 种排序关键字大白话区别 ​

Hive 有 4 种排序关键字,新手先重点掌握最常用的ORDER BY,其他了解特性即可。

表格

关键字核心特性适用场景
ORDER BY全局排序,对所有数据统一排序,结果完全有序小数据集精准排序、TOP N 统计,生产环境必须配合 LIMIT 使用
SORT BYReducer 内局部排序,仅保证单个 Reducer 内数据有序,整体结果无序大数据集局部排序,不要求全局有序
DISTRIBUTE BY控制数据按哈希值分发到不同 Reducer,不负责排序配合 SORT BY 实现分区内排序,解决数据倾斜
CLUSTER BY等价于DISTRIBUTE BY + SORT BY(同字段升序)同字段的分发与排序简化写法

2. ORDER BY 全局排序(最常用) ​

核心语法 ​

hive
SELECT 字段1, 聚合函数...
FROM 表名
[WHERE/GROUP BY/HAVING]
ORDER BY 排序字段1 [ASC|DESC], 排序字段2 [ASC|DESC]...;
  • ASC:升序排列(默认值,不写就是升序)
  • DESC:降序排列
  • 多字段排序:先按第一个字段排序,第一个字段值相同时,再按第二个字段排序

3. LIMIT 关键字:限制结果条数 + 分页 ​

核心语法 ​

hive
SELECT 字段...
FROM 表名
LIMIT [偏移量,] 返回条数;
  • 偏移量:可选,代表从第几条数据开始返回,默认从 0 开始
  • 返回条数:必填,限制最终返回的数据行数

入门案例 ​

hive
-- 代码4-27 只返回前2条数据
SELECT * 
FROM mediamatch_usermsg
LIMIT 2;

-- 代码4-28 分页查询:从第3条数据开始,返回2条(偏移量2,返回2条)
SELECT * 
FROM mediamatch_usermsg
LIMIT 2,2;

4. 核心业务案例(任务 4.7):统计用户人数最多的 3 种用户状态 ​

hive
-- 代码4-31 统计用户数TOP3的用户状态
SELECT 
  COUNT(*) as nums, 
  run_name AS `用户状态`
FROM mediamatch_usermsg
GROUP BY run_name
-- 按用户数降序排列
ORDER BY nums DESC
-- 只取前3条
LIMIT 3;

5. 新手避坑 ​

  • 大数据量下用ORDER BY不加 LIMIT,会导致所有数据进入一个 Reducer 处理,任务长时间卡死,生产环境严禁这么做
  • Hive 严格模式下(hive.mapred.mode=strict),ORDER BY必须配合 LIMIT 使用
  • DISTRIBUTE BY必须写在SORT BY前面,语法顺序不能乱

八、模块八:正则表达式模糊匹配字段名(进阶技巧) ​

1. 大白话理解 ​

当表的字段很多,我们想批量匹配符合规则的字段时(比如所有以_time结尾的时间字段),可以用正则表达式模糊匹配字段名,不用一个个手动写。

2. 前置配置 + 核心语法 ​

(1)必须先开的配置 ​

hive
-- 代码4-33 开启正则表达式匹配字段名支持
set hive.support.quoted.identifiers = none;

不开这个配置,正则表达式会被识别为普通字符串,无法匹配字段。

(2)核心语法 ​

正则表达式必须用 ** 反单引号 ``** 包裹,不能用单引号 / 双引号。

3. 核心业务案例(任务 4.8):查询客户发生状态变更的时间及开户时间 ​

两个时间字段都以_time结尾,用正则.*_time直接匹配所有符合规则的字段。

hive
-- 代码4-35 查询所有以_time结尾的时间字段
SELECT `.*_time`
FROM mediamatch_usermsg
LIMIT 10;

-- 代码4-34 正则匹配所有以phone开头的字段
SELECT `phone.*`
FROM mediamatch_usermsg
LIMIT 10;

九、新手高频踩坑避坑指南 ​

  1. 字段别名使用错误

    • 坑:在 WHERE/GROUP BY 里用列别名,导致报错
    • 解决:严格遵守执行顺序,WHERE/GROUP BY 用原始字段名,只有 ORDER BY 能用别名
  2. 空值判断错误

    • 坑:用字段 = NULL判断空值,查不到任何数据
    • 解决:空值判断必须用IS NULL/IS NOT NULL
  3. GROUP BY 语法报错

    • 坑:SELECT 里的字段既不在 GROUP BY 里,也没被聚合函数包裹
    • 解决:严格遵守铁则,SELECT 后的字段要么在 GROUP BY 里,要么用聚合函数包裹
  4. LIKE 通配符用错

    • 坑:把通配符%写成*,导致模糊匹配失效
    • 解决:LIKE 语法用%匹配任意字符,*仅在正则里生效
  5. 大数据量排序卡死

    • 坑:千万级数据用 ORDER BY 不加 LIMIT,导致任务长时间运行
    • 解决:ORDER BY 必须配合 LIMIT 使用,大数据量用 DISTRIBUTE BY + SORT BY 做局部排序
  6. 正则匹配失效

    • 坑:没开配置、用单引号包裹正则,导致匹配不到字段
    • 解决:先开启hive.support.quoted.identifiers = none,正则用反单引号 `` 包裹

十、入门自测题(学完检验成果) ​

题目 1 ​

请写出 SQL,查询所有正常使用状态(run_name 包含「正常」)的用户编号、用户状态、开户时间、用户地址,只返回前 20 条数据。

参考答案
hive
SELECT 
  phone_no AS `用户编号`,
  run_name AS `用户状态`,
  open_time AS `开户时间`,
  addressoj AS `用户地址`
FROM mediamatch_usermsg
WHERE run_name LIKE '%正常%'
LIMIT 20;

题目 2 ​

请写出 SQL,统计每个品牌的用户数量,按用户数量降序排列,只返回用户数大于 500 的品牌。

参考答案
hive
SELECT 
  sm_name AS `品牌名称`,
  COUNT(*) AS `用户数`
FROM mediamatch_usermsg
GROUP BY sm_name
HAVING COUNT(*) > 500
ORDER BY `用户数` DESC;

题目 3 ​

请写出 SQL,查询用户表中所有不重复的用户等级,按等级名称升序排列。

参考答案
hive
SELECT DISTINCT owner_name AS `用户等级`
FROM mediamatch_usermsg
ORDER BY `用户等级` ASC;

题目 4 ​

请写出 SQL,用正则表达式匹配用户表中所有以name结尾的字段,返回前 10 条数据。

参考答案
hive
-- 先开启正则支持
SET hive.support.quoted.identifiers = none;

-- 匹配所有以name结尾的字段
SELECT `.*name`
FROM mediamatch_usermsg
LIMIT 10;

基于 Vite 强力驱动 | 纯静态轻量托管