在数据分析的江湖中,数据往往分散在不同的“门派”(表)之中。要洞察数据间的深层联系,就需要JOIN这把利器,将相关联的数据串联起来。Hive SQL 提供了多种 JOIN语法,如同六脉神剑,各有精妙之处。掌握它们,能让你在数据整合时游刃有余。
准备工作:创建示例表
为了演示各种 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, '行政部');
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;
张三 技术部
李四 市场部
王五 技术部
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
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
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
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
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;
张三 技术部
张三 市场部
张三 行政部
李四 技术部
李四 市场部
李四 行政部
...
假设我们有如上创建的 employees
和 departments
表。
employees
表有100行,departments
表有5行,那么 CROSS JOIN
会产生多少行结果?SELECT e.emp_name
FROM employees e
JOIN departments d ON e.dept_id = d.dept_id
WHERE d.dept_name = '技术部';
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;
SELECT e.emp_name
FROM employees e
LEFT JOIN departments d ON e.dept_id = d.dept_id
WHERE d.dept_id IS NULL;
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;
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;
employees
表有100行,departments
表有5行,那么 CROSS JOIN
会产生多少行结果?
100 * 5 = 500 行。
SELECT e.emp_name, d.dept_name
FROM employees e
INNER JOIN departments d ON e.dept_id = d.dept_id;
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;
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;