暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【手写数据库核心揭秘系列】第99节 多表联合查询演示,高复杂度查询SQL,四张数据表混合联合类型的查询

开源无限 2025-06-12
43

💻 深耕数据库内核架构设计与开发十余年,曾主导多款高性能分布式数据库内核研发,攻克高并发、低延迟等核心技术难题。现倾力打造《从零手写数据库》系列教程,首次系统性公开数据库内核源码级实现细节!
🚀 从存储引擎、查询优化到分布式事务,手把手拆解核心模块;从语法解析树构建到执行计划生成,逐行代码还原设计精髓
🌟 无论你是数据库开发者、系统架构师,还是对底层技术充满好奇的极客,这里都有你想要的“硬核干货”!点击关注,与行业老兵共同探索数据库技术的星辰大海!


一、概述 


本节对于多表联合查询进行综合演示,经过前期对于语法和执行算子的实现,虽然做的很快,其实已经可以执行相当复杂的查询,而且对于多张数据表进行混合联合查询。

二、数据准备 



 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(10111001'2025-06-01'89.9), (10111002'2025-06-01'399.0) ,(10221003'2025-06-02'1299.5),(10311002'2025-06-03'399.0);


      INSERT INTO products VALUES(1001'line mouse''external equipment'89.91),(1002'Mechanical Keyboard''external equipment'399.02),(1003'display screen''display equipment'1299.51);


      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(line
        miniToad <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(line
          miniToad <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(line
            miniToad <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(line
              miniToad <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(line
                miniToad <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(line
                  miniToad <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(line
                    miniToad <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讲 联接执行算子二,左右联接、内联接及交叉联接执行处理技巧

                    【手写数据库内核miniToadb】第20天 开始删除表的支持,drop语句的词法解析

                    【手写数据库内核miniToadb】第30天 INSERT语法节点定义


                    文章转载自开源无限,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                    评论