首页 > 其他分享 >笛卡尔乘积

笛卡尔乘积

时间:2024-03-07 16:23:10浏览次数:18  
标签:JOIN 乘积 笛卡尔 SQL st 表中

SQL 中的笛卡尔积

SQL中的笛卡尔积是数学集合论中的一个术语。但是,我们也可以在 SQL 数据库手册中找到这个术语。它意味着什么,我们应该如何使用它?让我们来学习一下。

两个集合 X 和 Y 的笛卡尔积,表示为 X × Y,是所有有序对的集合,其中 x 在 X 中,y 在 Y 中。

就 SQL 而言,笛卡尔积是由两个表组成的新表。如果这些表分别有 3 行和 4 行,则笛卡尔乘积表将有 3×4 行。因此,第一个表中的每一行都连接第二个表的每一行。你得到两个集合的乘法结果,使原始集合的元素的所有可能的有序对。

笛卡尔积涉及大量计算运算,这些运算通常是冗余的。因此,对于大型表,我们建议使用限定符运算符。

如何在SQL中实现笛卡尔积?

在 SQL 中实现笛卡尔积可以通过返回两个表的叉积的 CROSS JOIN 运算符来实现。

让我们看一下下图中的示例。两个相应的表说明了颜色大小值。由于没有 JOIN 条件,因此颜色表中的所有行 (2) 都连接到大小表中的所有行 (4),从而生成 8 行作为结果。

 

在 SQL 中实现笛卡尔积

CROSS JOIN 方法适用于许多情况。例如,我们需要有一个办公室一个月的完整工资数据。即使月份 X 没有工资,您也可以将办公室与所有月份的表格交叉合并。

注意:在实践中,表的笛卡尔积并不常见。我们可能希望将所有员工与所有部门联系起来,但只有当每个人都按照一个计划工作,并且他们的工作影响所有部门时,这才是合理的。将所有员工/部门与所有__cpLocations联系起来完全是无稽之谈。

不过,有时数据库包含只有一行的表,用于存储一些常量(例如,公司名称)。在这里,我们可以使用笛卡尔乘积运算将此类表连接到任何查询。

在实践中使用笛卡尔乘积 SQL

笛卡尔乘积 SQL 在以下情况下很有用:

  • 省略 JOIN 条件;
  • JOIN 条件无效;
  • 第一个表中的所有行都与第二个表中的所有行连接起来。

如果需要仅选择那些相互匹配的记录,则表的笛卡尔乘积变得更加常见。我们可以通过使用 ON、USING 或 WHERE 指定选择条件来做到这一点。

有时,笛卡尔积是由于查询文本中的错误而发生的。联接表的主要方法是内部联接或自然联接操作。

笛卡尔乘积中的关节

关节在笛卡尔乘积实现中起着重要作用。它们是它的子集。

例如,n 个表的笛卡尔积是一个包含所有可能的 r 行的表。在这里,r 是第一个表中的一些行、第二个表中的行等,直到第 n个表中的行的串联。让我们看看我们是否可以使用 SELECT 语句获得笛卡尔积。

要获取多个表的笛卡尔积,请在 FROM 子句中指定相乘表的列表,并在 SELECT 子句中指定其所有列的列表。在我们的例子中,我们需要得到菜肴类型(5 行)和膳食(3 行)表的笛卡尔乘积:

SELECT type_of_dishes.*, meal.*
FROM type_of_dishes, meal;

 

结果是一个包含 5 x 3 = 15 行的表:

菜肴种类
小吃 早餐
小吃 午餐
小吃 晚餐
早餐
午餐
晚餐
主菜 早餐
主菜 午餐
主菜 晚餐
甜点 早餐
甜点 午餐
甜点 晚餐
早餐
午餐
晚餐

 

现在,我们将表菜单(20 行)、膳食(3 行)、菜肴类型(5 行)和菜肴(30 行)乘以以下查询:

SELECT Menu.*, Meal.*, Type_of_Dishes.*, Dishes.*
FROM Menu, Meal, Type_of_Dishes, Dishes;

 

我们得到一个包含 20 x 3 x 5 x 30 = 9000 行的表。

实践中表的内部 JOIN

内部 JOIN 只能将表与公共列合并。因此,当我们执行此操作时,它仅连接具有公共值的字符串。

通常,内部 JOIN 用于具有一对多关系的表。在这种情况下,主表的主键和从属表的外键充当关系列。因此,在内部 JOIN 期间,从属表中没有相关行的主表行将根本不包含在查询结果中。

在 SQL 中,有 2 种方法可以实现表的内部 JOIN。这两种方法是等效的,通常会导致相同的查询执行算法。让我们详细了解它们。

从笛卡尔积中选出

假设我们想要显示所有学生的姓名及其分数。相应的请求如下所示:

SELECT students.name_st, marks.mark
FROM students, marks
WHERE students.cod_st = marks.cod_st

 

JOIN操作

将学生与其分数联系起来的相同查询可以写得略有不同:

SELECT students .name_st, marks.mark
FROM students join marks
ON students.cod_st = marks.cod_st

 

这两个查询的结果相似,如下所示:

name_st mark
Smith Smith... Adams Adams Adams ...

 

每个学生的姓氏在结果表中重复的次数与学生获得分数的次数相同。例如,如果学生的表格包含一个姓氏为 Anderson 的行,而 Anderson 尚未获得任何分数,则该姓氏将根本不显示在生成的表格中。

这就是内部联接操作的工作方式。

我们需要注意上述示例的一些特征。

首先,查询文本使用用点表示法书写的复合列名:table_name.column_name

使用可分辨名称可避免列名记录中的歧义,因为不同的表可以包含同名的列。如果任何列的名称在 FROM 子句的表中是唯一的,则可以使用简单名称。但是,可分辨名称更好,因为此类查询的编译速度更快。

其次,在上面的两个查询中,我们明确指定了 JOIN 条件 – 关系列的相等性 (students.cod_st = marks.cod_st)。

从理论上讲,您可以缩短查询文本,因为 students 和 marks 表中只有一个公共列 (cod_st)。但是,联接两个表并不总是仅通过主键和外键完成。同一类型的任意两列可用于联接表。

使用关系的非键列链接行时要非常小心。例如,通过条件 students.cod_st = marks.cod_sub 定义关系的查询在语法上是正确的,但完全没有意义。

结论

一般来说,笛卡尔 SQL 产品会生成大量行,结果很少有用。因此,在使用 SQL 表时,最好避免使用笛卡尔乘积。应始终在 WHERE 子句中包含有效的 JOIN 条件,但特定需要合并所有表中的所有行的情况除外。

但是,笛卡尔乘积 SQL 可以应用于必须生成大量行来模拟所需数据量的测试。

标签:JOIN,乘积,笛卡尔,SQL,st,表中
From: https://www.cnblogs.com/cdaniu/p/18059154

相关文章

  • 编程语言中,差、交、并、自然连接、选择、投影、笛卡尔积分别都是什么运算...
    原文:https://blog.csdn.net/muzihuaner/article/details/119529646交(Intersection):关系R与关系S的交由既属于R又属于S的元组组成,即R与S中相同的元组,组成一个新关系,其结果仍为n目关系。记作:R∩S={t|t∈R∧t∈S}简单来说,运算结果就是两或多个实体集所共有的部分 并(Union):......
  • 乘积尾零 612
    如下的10行数据,每行有10个整数,请你求出它们的乘积的末尾有多少个零?565045423554473946411438719073904329275879496113565952457432305144346704359499371173686633974759755730702287145398991486572231351170401455105120729288090192......
  • 笛卡尔树学习笔记
    1.定义笛卡尔树是一种特殊的二叉树,同时满足小根堆和二叉搜索树的性质,笛卡尔树的每个节点有两个值(k,w),k满足二叉搜索树性质,w满足小根堆性质。Treap也是一种笛卡尔树2.性质如果k,w是分别两两不同的,那么笛卡尔树也是唯一的对于一颗笛卡尔树,它的中序遍历是原序列a在原序列中......
  • 笛卡尔树
    笛卡尔树定义以一个数列为基础,存储数列中元素,满足两个限制的树。一是数列中元素的下标满足二叉搜索树的性质,二是元素的大小满足堆的性质。建树使用单调栈,在线建树。考虑从左往右在已有的笛卡尔树中添加元素,因为新元素的下标最大,所以只可能取代最右链中的某个元素,并将其收为左......
  • 1339. 分裂二叉树的最大乘积
    这道题关键突破点就是先算出节点总和,然后找到一颗子树总和最接近总和的一半。乘积最大基本就是先要求总和,然后找到最接近总和一半。关键就是这一步,找到最适合子树的和。点击查看代码if(abs(2*cur-sum)<abs(2*best-sum)){best=cur;}完整代码:点击查看......
  • <学习笔记> 笛卡尔树
    笛卡尔树是一种二叉树,每一个节点由键值二元组\((k,w)\)构成,\(k\)满足二叉搜索树的性质,\(w\)满足堆的性质。构建我们可以用一个栈进行构建,假如我们想要求\(k\)满足二叉搜索树的性质,那么我们首先需要按\(k\)从小到大排序,然后一个一个插入;假如我们想要\(w\)满足小根......
  • F. 乘积最大(题解)
    题目今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年。在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友XZ也有幸得以参加。活动中,主持人给所有参加活动的选手出了这样一道题目:设有一个长度为......
  • 乘积小于k的子数组
    问题描述:给定一个正整数数组nums。找出该数组内乘积小于k的连续的子数组的个数。示例1:输入:nums=[10,5,2,6],k=100输出:8解释:8个乘积小于100的子数组分别为:[10],[5],[2],[6],[10,5],[5,2],[2,6],[5,2,6]。需要注意的是[10,5,2]并不是乘积小于100的......
  • Luogu P1249 最大乘积
    最大乘积题目描述一个正整数一般可以分为几个互不相同的自然数的和,如\(3=1+2\),\(4=1+3\),\(5=1+4=2+3\),\(6=1+5=2+4\)。现在你的任务是将指定的正整数\(n\)分解成若干个互不相同的自然数的和,且使这些自然数的乘积最大。输入格式只一个正整数\(n\),(\(3\leqn\leq10000\))。......
  • 洛谷题单指南-模拟和高精度-P1249 最大乘积
    原题链接:https://www.luogu.com.cn/problem/P1249题意解读:题目分两步,第一步是将整数拆分成不同自然数的和,第二步通过高精度计算这些因数的乘积,要使乘积最大,需要某种贪心思想。解题思路:如何保证整数拆分后因子的乘积最大呢,有几个原则:1、最好不要包括因子1,但3、4除外,需要进行特......