十一、Hive JOIN 连接查询

简介: 在 Hive 的世界里,JOIN 就像是数据间的红线,把原本分散在各自表里的信息串联起来。无论是内连接、外连接,还是 Hive 特有的左半连接,都各有“武功招式”,适用于不同场景。

数据分析江湖中,数据往往分散不同的“门派”(表)之中。要洞察数据间的深层联系,就需要JOIN这把利器,将相关联的数据串联起来。Hive SQL 提供了多种 JOIN语法,如同六脉神剑,各有精妙之处。掌握它们,能让你在数据整合游刃有余

思维导图

image.png

image.png

准备工作:创建示例表

为了演示各种 JOIN,我们先创建两张简单的表:employees (员工表) 和 departments (部门表)。

-- 员工表
CREATE TABLE employees (
emp_id INT,
emp_name STRING,
dept_id INT
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
STORED AS TEXTFILE;

-- 部门表
CREATE TABLE departments (
dept_id INT,
dept_name STRING
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
STORED AS TEXTFILE;

-- 插入数据
INSERT INTO employees VALUES
(1, '张三', 101),
(2, '李四', 102),
(3, '王五', 101),
(4, '赵六', 103),
(5, '孙七', NULL);

INSERT INTO departments VALUES
(101, '技术部'),
(102, '市场部'),
(104, '行政部');

Hive JOIN 六大语法详解

1. INNER JOIN (内连接,或简写为 JOIN)

  • 核心思想:只返回两张表中连接条件匹配的行。如果某行在一张表找不到另一张表中与之匹配的行,则该行不会出现在结果中。
  • 通用语法
    SELECT table1.col1, table1.col2, table2.col_other
    FROM table1
    INNER JOIN table2
    ON table1.join_column = table2.join_column;
    
  • 代码示例:查询所有有明确部门归属的员工及其部门名称。
    SELECT e.emp_name, d.dept_name
    FROM employees e
    INNER JOIN departments d
    ON e.dept_id = d.dept_id;
    
  • 预期输出
    张三    技术部
    李四    市场部
    王五    技术部
    

2. LEFT OUTER JOIN (左外连接,或简写为 LEFT JOIN)

  • 核心思想返回左表中所有的行,以及右表中与左表连接条件匹配的行。如果右表没有匹配的行,则右表列值显示为 NULL
  • 通用语法
    SELECT table1.col1, table1.col2, table2.col_other
    FROM table1
    LEFT OUTER JOIN table2
    ON table1.join_column = table2.join_column;
    
  • 代码示例:查询所有员工,并显示他们的部门名称(如果存在)。
    SELECT e.emp_name, e.dept_id AS emp_dept_id, d.dept_name
    FROM employees e
    LEFT JOIN departments d
    ON e.dept_id = d.dept_id;
    
  • 预期输出
    张三    101     技术部
    李四    102     市场部
    王五    101     技术部
    赵六    103     NULL
    孙七    NULL    NULL
    

3. RIGHT OUTER JOIN (右外连接,或简写为 RIGHT JOIN)

  • 核心思想:与 LEFT JOIN 相反。返回右表所有的行,以及左表中与右表连接条件匹配的行。如果左表没有匹配的行,则左表列值显示为 NULL
  • 通用语法
    SELECT table1.col1, table2.col_other1, table2.col_other2
    FROM table1
    RIGHT OUTER JOIN table2
    ON table1.join_column = table2.join_column;
    
  • 代码示例:查询所有部门,并显示部门下的员工姓名(如果存在)。
    SELECT e.emp_name, d.dept_name, d.dept_id AS dep_dept_id
    FROM employees e
    RIGHT JOIN departments d
    ON e.dept_id = d.dept_id;
    
  • 预期输出
    张三    技术部    101
    李四    市场部    102
    王五    技术部    101
    NULL    行政部    104
    

4. FULL OUTER JOIN (全外连接,或简写为 FULL JOIN)

  • 核心思想返回左表和右表中所有的行。当某行在另一张表没有匹配时,该表对应列值显示为 NULL
  • 通用语法
    SELECT table1.col1, table2.col_other
    FROM table1
    FULL OUTER JOIN table2
    ON table1.join_column = table2.join_column;
    
  • 代码示例:查询所有员工和所有部门的完整信息。
    SELECT e.emp_name, e.dept_id AS emp_dept_id, d.dept_name, d.dept_id AS dep_dept_id
    FROM employees e
    FULL JOIN departments d
    ON e.dept_id = d.dept_id;
    
  • 预期输出
    张三    101     技术部    101
    李四    102     市场部    102
    王五    101     技术部    101
    赵六    103     NULL    NULL
    孙七    NULL    NULL    NULL
    NULL    NULL    行政部    104
    

5. LEFT SEMI JOIN (左半连接)

  • 核心思想:这是 Hive 特有的一种 JOIN。它只返回左表中那些在右表存在匹配记录的行。关键在于,结果集中不包含右表的任何列。它更像是一个存在性检查 (类似于 SQL 中的 EXISTS 子查询)。
  • 通用语法
    SELECT table1.col1, table1.col2
    FROM table1
    LEFT SEMI JOIN table2
    ON table1.join_column = table2.join_column;
    
  • 代码示例:查询所有在部门表中确实存在对应部门的员工信息。
    SELECT e.emp_id, e.emp_name, e.dept_id
    FROM employees e
    LEFT SEMI JOIN departments d
    ON e.dept_id = d.dept_id;
    
  • 预期输出
    1       张三    101
    2       李四    102
    3       王五    101
    

6. CROSS JOIN (交叉连接,笛卡尔积)

  • 核心思想返回左表中的每一行与右表中的每一行所有可能组合。结果集的行数是左表行数乘以右表行数。通常不使用 ON 子句(或者使用 ON 1=1 这种恒为真的条件)。
  • 通用语法
    SELECT table1.col1, table2.col_other
    FROM table1
    CROSS JOIN table2;
    
  • 代码示例:显示员工和部门的所有可能组合(通常在实际业务中要谨慎使用)。
    SELECT e.emp_name, d.dept_name
    FROM employees e
    CROSS JOIN departments d;
    
  • 预期输出: (员工表5行 * 部门表3行 = 15行,部分示例)
    张三    技术部
    张三    市场部
    张三    行政部
    李四    技术部
    李四    市场部
    李四    行政部
    ...
    
  • 注意:CROSS JOIN 非常容易产生巨大的结果集,消耗大量资源,务必谨慎使用

练习题

假设我们有如上创建的 employeesdepartments 表。

  1. 找出所有在“技术部”工作的员工姓名。
  2. 列出所有部门的名称,以及该部门的员工数量(如果某部门没有员工,数量显示为0)。
  3. 找出所有没有分配到任何有效部门的员工姓名(即员工表中的dept_id在部门表中不存在,或者员工的dept_id为NULL)。
  4. 列出所有员工的姓名,以及他们所在部门的名称。对于没有部门的员工孙七,部门名称应显示为 "未分配";对于部门ID存在但部门表中无对应名称的赵六,部门名称应显示为 "未知部门"。
  5. 使用 LEFT SEMI JOIN,找出所有部门ID为101的员工信息。
  6. 解释 INNER JOIN 和 LEFT OUTER JOIN 在处理不匹配数据时的主要区别。
  7. 如果 employees 表有100行,departments 表有5行,那么 CROSS JOIN 会产生多少行结果?
  8. 找出所有既有员工,其部门也在部门表中存在的员工姓名和部门名称。(提示:思考多种JOIN方式)
  9. 使用 FULL OUTER JOIN,然后筛选出只存在于员工表(在部门表无匹配)或只存在于部门表(在员工表无匹配)的记录。请描述如何筛选。
  10. 查询所有部门ID (dept_id),以及这些部门的名称。如果一个部门ID只存在于员工表中,也需要列出这个ID,但部门名称显示为NULL。

练习题答案

  1. 找出所有在“技术部”工作的员工姓名。

    SELECT e.emp_name
    FROM employees e
    JOIN departments d ON e.dept_id = d.dept_id
    WHERE d.dept_name = '技术部';
    
  2. 列出所有部门的名称,以及该部门的员工数量(如果某部门没有员工,数量显示为0)。

    SELECT d.dept_name, COUNT(e.emp_id) AS employee_count
    FROM departments d
    LEFT JOIN employees e ON d.dept_id = e.dept_id
    GROUP BY d.dept_id, d.dept_name;
    
  3. 找出所有没有分配到任何有效部门的员工姓名(即员工表中的dept_id在部门表中不存在,或者员工的dept_id为NULL)。

    SELECT e.emp_name
    FROM employees e
    LEFT JOIN departments d ON e.dept_id = d.dept_id
    WHERE d.dept_id IS NULL;
    
  4. 列出所有员工的姓名,以及他们所在部门的名称。对于没有部门的员工孙七,部门名称应显示为 "未分配";对于部门ID存在但部门表中无对应名称的赵六,部门名称应显示为 "未知部门"。

    SELECT
    e.emp_name,
    CASE
    WHEN e.dept_id IS NULL THEN '未分配'
    WHEN d.dept_name IS NULL THEN '未知部门'
    ELSE d.dept_name
    END AS department_status
    FROM employees e
    LEFT JOIN departments d ON e.dept_id = d.dept_id;
    
  5. 使用 LEFT SEMI JOIN,找出所有部门ID为101的员工信息。

    SELECT e.emp_id, e.emp_name, e.dept_id
    FROM employees e
    LEFT SEMI JOIN departments d ON e.dept_id = d.dept_id AND e.dept_id = 101;
    
  6. 解释 INNER JOIN 和 LEFT OUTER JOIN 在处理不匹配数据时的主要区别。
    INNER JOIN 只保留两边表中都能通过连接条件找到匹配的行。如果左表的一行在右表中没有匹配,或者右表的一行在左表中没有匹配,这些行都会被丢弃。
    LEFT OUTER JOIN 会保留左表的所有行。如果左表的某行在右表中找到了匹配,则合并两边的列;如果在右表中找不到匹配,则右表对应的列将填充为NULL,但左表的行仍然会出现在结果中。

  7. 如果 employees 表有100行,departments 表有5行,那么 CROSS JOIN 会产生多少行结果?
    100 * 5 = 500 行。

  8. 找出所有既有员工,其部门也在部门表中存在的员工姓名和部门名称。(提示:思考多种JOIN方式)

    SELECT e.emp_name, d.dept_name
    FROM employees e
    INNER JOIN departments d ON e.dept_id = d.dept_id;
    
  9. 使用 FULL OUTER JOIN,然后筛选出只存在于员工表(在部门表无匹配)或只存在于部门表(在员工表无匹配)的记录。请描述如何筛选。
    筛选条件是:当 employees.emp_id IS NULL (表示这条记录只在departments表中有) 或者 departments.dept_id IS NULL (表示这条记录只在employees表中有,且连接失败)。

    SELECT e.emp_name, e.dept_id AS emp_dept_id, d.dept_name, d.dept_id AS dep_dept_id
    FROM employees e
    FULL OUTER JOIN departments d ON e.dept_id = d.dept_id
    WHERE e.emp_id IS NULL OR d.dept_id IS NULL;
    
  10. 查询所有部门ID (dept_id),以及这些部门的名称。如果一个部门ID只存在于员工表中,也需要列出这个ID,但部门名称显示为NULL。

    SELECT DISTINCT e.dept_id AS emp_dept_id_distinct, d.dept_name
    FROM employees e
    LEFT JOIN departments d ON e.dept_id = d.dept_id;
    
目录
相关文章
|
4月前
|
SQL 存储 数据管理
七、深入 Hive DDL:管理表、分区与洞察元数据
在日常使用 Hive 的过程中,我们不仅要会建表,更要学会灵活地维护和管理已有的数据结构。从添加字段到修改分区,从查看元数据到删除表或清空数据,掌握这些 DDL 操作和常用的 SHOW 命令,就像掌握了一套管理数据仓库的“万能钥匙”。这次将带你一步步熟悉这些命令的用法和实际应用场景,配合清晰的语法示例与练习题,帮助你更轻松地驾驭 Hive 数据管理的日常工作。
444 6
|
4月前
|
SQL 存储 分布式计算
九、HQL DQL七大查询子句
Hive 查询写得清楚,数据分析就能更顺手。我们这次从入门角度出发,带你理清 Hive 中最常用的七个查询子句(FROM、WHERE、GROUP BY、HAVING、SELECT、ORDER BY、LIMIT),结合执行顺序梳理每一步的用法与注意事项。每个子句都有配套案例,还有实战练习题帮你快速上手。如果你刚开始学习 Hive 查询,或希望把基础打得更扎实,这篇内容值得收藏。
196 9
|
4月前
|
SQL Java 关系型数据库
二、Hive安装部署详细过程
手把手教你完成 Hive 的安装、配置和可视化连接,适合初学者快速搭建自己的大数据分析平台。内容涵盖从环境准备、Metastore配置,到 DataGrip 连接的全流程,并附带实用的排错指南,助你轻松迈出 Hive 入门第一步。
979 14
|
4月前
|
SQL 存储 Apache
三、Hive DDL数据库操作
Hive 中的数据库(Schema)是构建数据仓库的基础单位。这次我们来了解 Hive 中创建、查看、切换、修改与删除数据库的 DDL 操作语法与用法,涵盖 COMMENT、LOCATION、DBPROPERTIES 等常用参数,辅以丰富示例与练习,助你扎实掌握 Hive 数据库管理核心能力。
275 11
|
4月前
|
SQL 数据采集 存储
六、Hive 分桶
在 Hive 的世界里,除了常见的分区,分桶也是一项非常实用的数据优化方式。它能帮助我们将数据按某个字段均匀划分到多个“桶”中,不仅能提升大表连接的效率,还特别适合做数据抽样和精细管理。本文将带你一步步了解分桶表的创建方法、数据加载过程和常见应用场景,配有丰富示例和练习题,帮助你在实战中轻松掌握这项技能。
366 7
|
4月前
|
SQL 存储 JSON
四、Hive DDL表定义、数据类型、SerDe 与分隔符核心
Hive 中的表是数据仓库的核心容器,定义了数据的结构和存储方式。本文系统讲解了 Hive 中创建表的语法与关键参数,包括字段类型、分隔符设置、SerDe 使用等内容,特别通过结构化与复杂数据类型(如 ARRAY、MAP、STRUCT)的案例讲解,让读者理解如何让 Hive 正确“读懂”你的数据。配合常见示例与练习题,帮你打好 Hive 表设计的基础,轻松驾驭文本、JSON 等多格式数据。数据如何入库、如何被解析,一文看懂!
208 12
|
4月前
|
SQL 存储 分布式计算
五、Hive表类型、分区及数据加载
在 Hive 中设计表,绝不仅是“建个结构那么简单”。选对内部表或外部表,决定了数据的归属和生命周期;设计合理的静态/动态分区策略,则直接关系到大数据场景下的查询效率和存储管理成本。本文深入讲解 Hive 表类型与分区机制,配合大量实战代码与练习题,带你从“写对语法”走向“设计合理”,让你的数仓查询快到飞起!
281 11
|
SQL 存储 Oracle
【赵渝强老师】Hive的分区表
Hive的分区表与Oracle、MySQL类似,通过分区条件将数据分隔存储,提高查询效率。本文介绍了静态分区表和动态分区表的创建与使用方法,包括具体SQL语句和执行计划分析,附带视频讲解。静态分区表需显式指定分区条件,而动态分区表则根据插入数据自动创建分区。
1587 1
|
SQL Java 数据库连接
MyBatis-Plus快速入门:从安装到第一个Demo
本文将带你从零开始,快速入门 MyBatis-Plus。我们将首先介绍如何安装和配置 MyBatis-Plus,然后通过一个简单的示例演示如何使用它进行数据操作。无论你是 MyBatis 的新手还是希望提升开发效率的老手,本文都将为你提供清晰的指导和实用的技巧。
3286 0
MyBatis-Plus快速入门:从安装到第一个Demo
|
SQL 数据处理 HIVE
HIVE的数据倾斜调优
hive数据倾斜主要是由shuffle引起的,而引起shuffle的又主要有四种情况,分别为: 1.group by 2.join 3.count(distinct) 4.开窗函数
892 8