当我进行如下查询时,做笛卡尔积(交叉连接)背后的想法是什么 -
SELECT * FROM agents, orders
我认为它们会连接(如pandas)。添加表格而不是相乘感觉更自然。
只是好奇,并没有在互联网上找到默认笛卡尔积背后的理由。我假设FROM table1, table2
根据 SQL 的语法对于交叉连接可能会更正确,但为什么呢?
当我进行如下查询时,做笛卡尔积(交叉连接)背后的想法是什么 -
SELECT * FROM agents, orders
我认为它们会连接(如pandas)。添加表格而不是相乘感觉更自然。
只是好奇,并没有在互联网上找到默认笛卡尔积背后的理由。我假设FROM table1, table2
根据 SQL 的语法对于交叉连接可能会更正确,但为什么呢?
逗号样式连接 (SQL-89) 与使用
JOIN
关键字 (SQL-92) 的语法不是重点。您应该使用更现代的语法,但它没有解决如果您不指定条件,为什么默认会是笛卡尔积的问题。答案是它使关系代数起作用。
笛卡尔积是两组元素的所有组合的集合。第一组的每个元素都与第二组的每个元素配对。
关系是笛卡尔积的子集。这是一个笛卡尔积,加上一个测试任何给定元素对是否属于该关系的条件。
但是默认条件是一个固定
true
值,所以每个配对都通过了测试。所以默认关系最终是笛卡尔积。我想另一种选择是将默认条件设为固定
false
值,因此默认关系将是空关系。这会使某些场景变得更容易,例如,如果您运行 a
DELETE
但不小心忘记了该WHERE
子句,它将避免您删除整个表。WHERE
但是随后我们会收到来自不同人的关于 Stack Overflow 的问题,他们问为什么默认连接是一个空集,因为当他们忘记查询子句SELECT
并且他们的数据库似乎是空的时,这会让他们心跳加速。我不熟悉concatenate在Pandas中的工作方式,但我认为这
CROSS JOIN
是唯一有意义的子句,在这种情况下没有指定任何其他内容。您当然不能垂直连接(
UNION
在 SQL 中)表,因为它们的列可能不同(列数及其数据类型)以及如何水平连接它们,即在什么条件下可以将每个表中的行对齐到当没有指定任何内容时,将它们作为单行关联在一起?我认为在关系逻辑的上下文中最简单的答案是CROSS JOIN
.此外,Pandas中的连接似乎意味着对与关系数据库不同类型的对象进行操作。虽然在技术上是的,但这些对象可以被视为一组值,但描述它们的标准和这些值所依据的约束与具有观察不同数据类型的列的关系记录表不同,并且可能受到数据库约束的约束, ETC。
为了在 SQL 中实现与Pandas中单个连接操作类似的结果,您需要应用一系列操作,例如,可能包括、和。
PIVOT
UNION
CAST
Lennart的评论留下了答案:
SQL 尝试实现在“大型共享数据库的数据关系模型” (pdf) 中定义的关系模型。
我认为为什么选择符号“,”来表示其中一种操作和特别是笛卡尔积,我认为没有一个很好的答案。
您不应该使用(
,
逗号)作为CROSS JOIN
子句的代理来加入您的表。它提供了CROSS JOIN
功能,但要付出代价——可读性、清晰性和明确性——后一个词意味着清晰和准确的质量(不确定它是否存在)!至于您关于“
why the comma
”的问题(过去,但不再是 - 或者至少它已经失宠),请参阅下面的讨论!软件在维护模式下花费的时间比在开发中花费的时间更多,因此您的软件易于阅读和维护非常重要!
A
CROSS JOIN
在逻辑上可以被认为是这样的(来自这里的漂亮图像):另一种(同样有用的)看待这个的方法是(相同的链接):
因此,显然
CROSS JOIN
s 具有有用的、日常的、实际的应用程序!考虑以下三个查询(请参阅此处的小提琴):
结果(所有查询都相同):
查询一:
因此,对于查看该查询的开发人员,他们可能会说:“有多少字段?”,“这些字段有什么作用?” 或“此查询的性能影响是什么?”。我们只是 0% 的方式变得明确!
现在,这个:
查询 2:
稍微清楚一点——至少我们可以从 10,000m 看到这是一个,因为
CROSS JOIN
这个术语是黑白的!所以,我们大约有 33% 的方式是明确的!最后,考虑这个(最好的):
查询 3:
所以,现在,我们尽可能明确。有一个替代方案,那就是(稍微降低清晰度 - 但比逗号更清晰!):
最后,
查询 4(也运行...):
我会敦促你看看这篇优秀的文章(显式编码纪律- BIG ONE是第 3 名):
作者将其总结为:
为什么是逗号?
至于逗号——它只是一种语法、符号——可能,如果现在正在设计 SQL ,它不会是作为表方式的第一选择(或任何选择)
CROSS JOIN
。术语CONCAT JOIN
(à la Python 语法......)可能是一个潜在的候选者(对于从头设计) - 但现在我们(SQL 开发人员/DBA)已经习惯了,这听起来很奇怪CROSS JOIN
。此外,查询中各个字段的分隔符是逗号:
因此,它可能(在我之前......)将它用作表格分隔符也是合乎逻辑的。
最重要的是表达的清晰,不要忘记 SQL比 Python 早很多(约 20 年),而且许多语言都有过去的遗留物,最好将其删除 - 但只要考虑中断从Python 2 到 Python 3 - 已经(并且继续)造成了重大困难(作为记录,我钦佩 Guido van Rossum 做出改变的勇气 - 代码损坏......)。
SQL 的问题在于它是由委员会设计的,至少从我的经验来看,“
courage
”不是我会与委员会联系起来的特征!:-) 逗号已经失宠,许多严肃的从业者不鼓励它,但它并没有(不幸地)随着 更清晰的ANSIJOIN
的到来而被淘汰。ps 欢迎来到论坛!