一、概述
本节对于多表联合查询进行综合演示,经过前期对于语法和执行算子的实现,虽然做的很快,其实已经可以执行相当复杂的查询,而且对于多张数据表进行混合联合查询。
二、数据准备
2.1 创建表
为了演示效果,准备四张数据表:客户信息表、订单表、产品表和供应商表。
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line-- 表1:客户信息表 (customers)CREATE TABLE customers (cust_id INTEGER,name VARCHAR,city VARCHAR,membership_level CHAR);-- 表2:订单表 (orders)CREATE TABLE orders (order_id INTEGER,cust_id INTEGER, product_id INTEGER, order_date VARCHAR,total_amount FLOAT);-- 表3:产品表 (products)CREATE TABLE products (product_id INTEGER,product_name VARCHAR,category VARCHAR,price FLOAT,supplier_id INTEGER);-- 表4:供应商表 (suppliers)CREATE TABLE suppliers (supplier_id INTEGER,supplier_name VARCHAR,country VARCHAR,contact_name VARCHAR);
2.2 初始化数据
插入一些数据。
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line-- 插入示例数据INSERT INTO customers VALUES(1, 'zhangsan', 'beijin', 'A'),(2, 'lisi', 'shanghai', 'B'),(3, 'wangwu', 'guangzhou', 'C');INSERT INTO orders VALUES(101, 1, 1001, '2025-06-01', 89.9), (101, 1, 1002, '2025-06-01', 399.0) ,(102, 2, 1003, '2025-06-02', 1299.5),(103, 1, 1002, '2025-06-03', 399.0);INSERT INTO products VALUES(1001, 'line mouse', 'external equipment', 89.9, 1),(1002, 'Mechanical Keyboard', 'external equipment', 399.0, 2),(1003, 'display screen', 'display equipment', 1299.5, 1);INSERT INTO suppliers VALUES(1, 'Electronic technology company', 'China', 'Manager chen'),(2, 'Equipment specialist', 'Germany', 'Hans Muller');
三、两表的联合查询
在两张数据表上联合查询结果,演示内联接、左右外联接和交叉联接。
3.1 内连接(INNER JOIN)
查询顾客的订单金额,需要将顾客信息表与订单表通过顾客ID进行联合,才能找到对应的顾客名称和订单金额。
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineminiToad <# SELECT c.name as customer, o.order_id as order, o.total_amount as amount FROM customers c inner join orders o on c.cust_id=o.cust_id;|customer |order |amount ||zhangsan |101 |89.900002 ||zhangsan |101 |399.000000 ||zhangsan |103 |399.000000 ||lisi |102 |1299.500000 |excutor return 4 rows
可以发现一个有意思的事情,浮点数字在计算机中存储会有精度的偏差,在有限小数精确度内使用却没有问题。
3.2 左外连接(LEFT JOIN)
查询所有注册顾客的订单信息,当然包括无订单的顾客。
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineminiToad <# SELECT c.name AS customer, o.order_id as order FROM customers c LEFT JOIN orders o ON c.cust_id = o.cust_id;|customer |order ||zhangsan |101 ||zhangsan |101 ||zhangsan |103 ||lisi |102 ||wangwu |Null |excutor return 5 rows
此时左表为全部数据行,在右表中不符合联接条件时,用NULL进行显示右表内容。
3.3 右外连接(RIGHT JOIN)
查询所有订单的顾客信息,与上一例的分析视角刚好相反。
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineminiToad <# SELECT o.order_id AS order, c.name AS customer FROM customers c RIGHT JOIN orders o ON c.cust_id = o.cust_id;|order |customer ||101 |zhangsan ||101 |zhangsan ||102 |lisi ||103 |zhangsan |excutor return 4 rows
可以看到有的顾客会有多笔订单。
3.4 交叉联接
交叉联接,也就是两张数据表做笛卡尔积,总行数是两张数据表行数的乘积,左表中每一行会与右表中的每一行拼成结果。
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineminiToad <# select c.name as customer, p.product_name as product from customers c cross join products p where c.city = 'beijin';|customer |product ||zhangsan |line mouse ||zhangsan |Mechanical Keyboard ||zhangsan |display screen |excutor return 3 rows
可以看到同一顾客会出现多行,与所有产品信息拼接。
四、三表联合查询
三张数据表的联合查询,在内部处理时,通过嵌套联合,先两张数据表进行联合产生结果,再将结果与第三张数据表联合,产生最终的联合查询结果。
4.1 内连接(INNER JOIN)
查询顾客购买的商品及时间,在产品表和订单表联接时,模拟产品编号与订单编号可以做联接条件。
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineminiToad <# SELECT c.name AS customer, o.order_date AS order_date, p.product_name AS product_name FROM customers c INNER JOIN orders o ON c.cust_id = o.cust_id INNER JOIN products p ON o. product_id = p.product_id;|customer |order_date |product_name ||zhangsan |2025-06-01 |line mouse ||zhangsan |2025-06-01 |Mechanical Keyboard ||zhangsan |2025-06-03 |Mechanical Keyboard ||lisi |2025-06-02 |display screen |excutor return 4 rows
4.2 三表左外连接(LEFT JOIN)
查询顾客购买的商品及时间,在产品表和订单表联接时,模拟产品编号与订单编号可以做联接条件。
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineminiToad <# SELECT c.name AS customer, o.total_amount AS amount, p.product_name AS product FROM customers c LEFT JOIN orders o ON c.cust_id = o.cust_id LEFT JOIN products p ON o.product_id = p.product_id;|customer |amount |product ||zhangsan |89.900002 |line mouse ||zhangsan |399.000000 |Mechanical Keyboard ||zhangsan |399.000000 |Mechanical Keyboard ||lisi |1299.500000 |display screen ||wangwu |Null |Null |excutor return 5 rows
五、四表联合查询
多种联接类型可以在多表联合时混合使用,达到预期的结果集。
5.1 四表混合连接(INNER + LEFT JOIN)
查询顾客名,订单日期,产品名和供货国产信息,涉及到顾客信息表、订单表、产品表和供货商表。
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineminiToad <# SELECT c.name AS customer, o.order_date AS order_date, p.product_name AS product_name, s.country AS sup_contry FROM customers c INNER JOIN orders o ON c.cust_id = o.cust_id LEFT JOIN products p ON o.product_id = p.product_id LEFT JOIN suppliers s ON p.supplier_id = s.supplier_id;|customer |order_date |product_name |sup_contry ||zhangsan |2025-06-01 |line mouse |China ||zhangsan |2025-06-01 |Mechanical Keyboard |Germany ||zhangsan |2025-06-03 |Mechanical Keyboard |Germany ||lisi |2025-06-02 |display screen |China |excutor return 4 rows
因为顾客有重复的订单,所以有重复的数据行存在,这就需要去重操作,这在未来进一步实现。
【手写数据库核心揭秘系列】第98讲 联接执行算子二,左右联接、内联接及交叉联接执行处理技巧
文章转载自开源无限,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




