当前位置: 首页 > web >正文

mysql中cross join于普通join的区别

今天在写力扣的时候发现一道题,需要笛卡尔积做多表查询,发现cross join和普通join之间其实是一个东西,可以随意转换。
题目

题目背景(简化版)

假设我们有两张表:

  • 学生表(Students):存着学生的编号和姓名,比如 (1, '张三'), (2, '李四')
  • 考试表(Exams):存着考试的编号和科目,比如 (101, '数学'), (102, '英语'), (103, '物理')

先说Cross Join:暴力配对所有可能

核心逻辑:把学生表和考试表的每一行都强行“配对”,生成所有可能的组合,就像做排列组合题。
比如:

  • 学生表有2个学生,考试表有3个考试,CROSS JOIN 后会得到 2×3=6条记录,每条记录都是“某个学生+某个考试”的组合,不管这个学生有没有参加过这个考试。

SQL示例(对应题目可能的需求:列出所有学生可能参加的考试组合):

SELECT s.student_name, e.subject_name
FROM Students s CROSS JOIN Exams e;

结果大概长这样

student_namesubject_name
张三数学
张三英语
张三物理
李四数学
李四英语
李四物理

口语化理解:就像老师让全班同学和所有科目“组队”,不管你有没有选这门课,先把所有可能的“人+科目”组合列出来,纯凑数!

再聊普通Join(比如Inner Join):只留符合条件的配对

核心逻辑:必须按条件筛选,只保留两表中“有关系”的记录。比如,只有当学生真正参加了某场考试时,才会被加入结果。

假设我们有第三张表:学生考试记录表(StudentExams),记录谁参加了哪场考试,比如 (1, 101), (1, 102), (2, 101)(张三考了数学和英语,李四考了数学)。

SQL示例(查“参加过考试的学生和科目”):

SELECT s.student_name, e.subject_name
FROM Students s 
INNER JOIN StudentExams se ON s.student_id = se.student_id
INNER JOIN Exams e ON se.exam_id = e.exam_id;

结果大概长这样

student_namesubject_name
张三数学
张三英语
李四数学

口语化理解:现在老师只让“真正参加了考试的人+科目”组队,没参加的不显示。比如李四没考英语和物理,所以这两个组合就被筛掉了。

两者的灵魂区别对比

场景Cross Join普通Join(如Inner Join)
目的生成所有可能的组合(不管有没有关系)只取“有关系”的组合(按条件筛选)
结果数量学生数 × 考试数(比如2×3=6)取决于实际参加考试的记录数(可能更少)
类比全班同学和所有科目强行组队,先列全再筛选只让“报了名的同学+科目”组队,精准匹配
在本题中的应用题目可能需要统计“每个学生对所有科目的考试情况”,即使没参加也显示(用Cross Join)题目可能需要统计“实际参加过的考试”(用Inner Join)

为什么这题可能用到Cross Join?

假设题目要求:列出每个学生对所有科目的考试次数,没参加过的科目次数记为0。这时候就需要先用Cross Join生成“所有学生+所有科目”的组合,再通过分组统计次数,没参加过的自然就是0啦~

比如:

  1. Cross Join得到所有组合(张三+数学,张三+英语,张三+物理,李四+数学,李四+英语,李四+物理)。
  2. 再左连接考试记录表,没参加过的考试记录为NULL,统计时NULL会被计为0。

在SQL中,JOIN(连接)和CROSS JOIN(交叉连接)都是用于组合多张表数据的操作,但它们的逻辑和结果有显著区别:

1. CROSS JOIN(交叉连接)

  • 核心逻辑:生成两张表的笛卡尔积(Cartesian product),即左表的每一行与右表的每一行都强制组合成一条新记录。
  • 特点
    • 不需要任何连接条件(ONWHERE),如果添加条件会改变其性质。
    • 结果集行数 = 左表行数 × 右表行数,数据量可能非常大(需谨慎使用)。
  • 语法
    -- 显式写法
    SELECT * FROM 表A CROSS JOIN 表B;-- 隐式写法(等价,用逗号分隔表)
    SELECT * FROM 表A, 表B;
    
  • 示例
    表A(2行)和表B(3行)交叉连接后产生 2×3=6 行,包含所有可能的组合。

2. JOIN(普通连接,如INNER JOIN、LEFT JOIN等)

  • 核心逻辑:根据指定的连接条件ON子句)筛选出符合条件的记录组合,只保留匹配的行。
  • 常见类型
    • INNER JOIN(内连接):只保留两表中完全匹配条件的记录。
    • LEFT JOIN(左连接):保留左表所有记录,右表匹配不到则补NULL
    • RIGHT JOIN(右连接):保留右表所有记录,左表匹配不到则补NULL
  • 特点
    • 必须有连接条件(ON子句),否则会退化为CROSS JOIN
    • 结果集行数由匹配条件决定,通常远小于笛卡尔积。
  • 语法
    -- 内连接示例(只保留匹配的行)
    SELECT * FROM 表A INNER JOIN 表B ON 表A.id = 表B.a_id;-- 左连接示例(保留左表所有行)
    SELECT * FROM 表A LEFT JOIN 表B ON 表A.id = 表B.a_id;
    

关键区别总结

维度CROSS JOIN普通JOIN(如INNER JOIN)
连接条件不需要,强制全组合必须有ON条件,筛选匹配记录
结果集性质笛卡尔积(所有可能组合)符合条件的匹配记录
行数左表行数 × 右表行数取决于匹配条件,通常较少
适用场景需全量组合的特殊场景(如生成测试数据)需关联两表字段的常规查询

补充说明

  • 普通JOIN如果省略ON条件,会自动变成CROSS JOIN(不推荐,易出错)。
  • CROSS JOINWHERE条件后,逻辑上等价于INNER JOIN(但建议直接用INNER JOIN更清晰)。

例如,以下两种写法结果相同,但后者更规范:

-- 不推荐:CROSS JOIN + WHERE 等价于 INNER JOIN
SELECT * FROM 表A CROSS JOIN 表B WHERE 表A.id = 表B.a_id;-- 推荐:显式内连接
SELECT * FROM 表A INNER JOIN 表B ON 表A.id = 表B.a_id;
http://www.xdnf.cn/news/19207.html

相关文章:

  • 无懈可击的 TCP AIMD
  • 网络请求优化:用 Retrofit 拦截器玩转日志、重试与缓存,OkHttp 和 Volley 谁更香?
  • STM32 USBx Device MSC standalone 移植示例 LAT1488
  • Product Hunt 每日热榜 | 2025-08-29
  • typescript postgres@3.x jsonb数据插入绕过类型检测错误问题
  • SwiGLU激活函数的原理
  • TensorFlow 面试题及详细答案 120道(51-60)-- 模型保存、加载与部署
  • 微软正在公开测试其首个完全自主训练的大语言模型——MAI-1-preview
  • python 日常学习记录
  • Java全栈开发工程师面试实录:从基础到微服务的深度技术解析
  • 【python】相机输出图片时保留时间戳数据
  • Blender模拟结构光3D Scanner(三)获取相机观测点云的真值
  • 信息系统生命周期
  • 小程序版碰一碰发视频:源码搭建与定制化开发的源头技术解析
  • CSS scale函数详解
  • nginx 怎么将 https 请求转为 http
  • Docker 实战 -- EMQX
  • 第22章笔记|把“可传参脚本”打磨成“高级好用的工具”
  • 链表(LinkedList)
  • docker compose设置命令别名的方法
  • Swift 解法详解:LeetCode 366《寻找二叉树的叶子节点》
  • 贪心算法面试常见问题分类解析
  • 微服务入门指南(一):从单体架构到服务注册发现
  • PPT处理控件Aspose.Slides教程:使用 C# 编程将 PPTX 转换为 XML
  • Pytorch超分辨率模型实现与详细解释
  • CRYPT32!CryptMsgUpdate函数分析和asn.1 editor nt5inf.cat 的总览信息
  • 机器学习回顾——逻辑回归
  • Consul 操作命令汇总 - Prometheus服务注册
  • 计算机视觉与深度学习 | 视觉里程计技术全景解析:从原理到前沿应用
  • 2024年09月 Python(四级)真题解析#中国电子学会#全国青少年软件编程等级考试