Sql 为什么完全联接顺序在这些查询中会产生差异?

Sql 为什么完全联接顺序在这些查询中会产生差异?,sql,postgresql,null,outer-join,associativity,Sql,Postgresql,Null,Outer Join,Associativity,我正在使用PostgreSQL。我在这里读到的所有内容都表明,在对单个列使用完全联接的查询中,联接的表的顺序基本上并不重要 我的直觉告诉我,这也适用于多个列,只要查询中尽可能列出每个公共列(也就是说,只要两个联接表都有公共列)。但事实并非如此,我正试图找出原因 简化为三个表a、b和c Columns in table a: id, name_a Columns in table b: id, id_x Columns in table c: id, id_x 此查询: SELECT * FRO

我正在使用PostgreSQL。我在这里读到的所有内容都表明,在对单个列使用完全联接的查询中,联接的表的顺序基本上并不重要

我的直觉告诉我,这也适用于多个列,只要查询中尽可能列出每个公共列(也就是说,只要两个联接表都有公共列)。但事实并非如此,我正试图找出原因

简化为三个表a、b和c

Columns in table a: id, name_a
Columns in table b: id, id_x
Columns in table c: id, id_x
此查询:

SELECT *
FROM a
    FULL JOIN b USING(id)
    FULL JOIN c USING(id, id_x);
返回与此不同的行数:

SELECT *
FROM a
    FULL JOIN c USING(id)
    FULL JOIN b USING(id, id_x);
我想要/期望的东西很难表达,但基本上,我想要一个“完全”的完全合并。我不希望任何地方出现空字段,除非这是不可避免的

例如,每当存在NOTNULL id时,我希望相应的名称列始终具有名称_a且不为null。相反,其中一个示例查询返回半冗余结果,其中一行具有名称但没有id,另一行具有id但没有名称,而不是单个合并行


当连接按其他顺序列出时,我确实得到了期望的结果(但我不确定还会发生什么其他问题,因为未来的数据未知)。

您的查询不同

在第一个示例中,您使用一列
id
b
执行
完全联接

在第二个示例中,使用两列对
b
进行
完全联接


尽管这两个查询在某些情况下可能返回相同的结果,但没有理由认为结果是可比较的。

参数顺序在外部联接中很重要,除了完全自然联接是对称的。它们返回内部联接(ON、USING或NATURAL)所执行的操作,还返回由null扩展的左(left-JOIN)、右(right-JOIN)或两个(FULL-JOIN)表中不匹配的行

使用返回内部联接行中每个指定列的单个共享值;在NULL扩展行中,另一个公共列在一个表的版本中可以有NULL,在另一个表的版本中可以有一个值

加入秩序也很重要。即使是完全自然联接也不是关联的,因为对于多个表,每对表(操作数是原始的或联接结果)都可以有一组唯一的公共列,即通常(a⟗ (B)⟗ C≠ A.⟗ (B)⟗ C)

在许多特殊情况下,某些附加身份仍然有效。例如,使用所有公共列名的完全联接和相同命名列相等的外部联接是对称的。有些情况涉及CKs(候选键)、FKs(外键)和其他参数约束


您的问题没有明确说明您正在假设什么样的输入条件,或者您正在寻找什么样的输出条件。

这是有道理的。但我不完全明白的是,如何强制最后一个表的
id
始终与第一个表的id融合,就像与第二个表融合一样。直观地说,当我使用
关键字
时,我希望
完全连接
能够正常工作,因为只返回一列
id
。@Lenoxus“始终融合”是什么意思?PS定义,不是直觉。我理解为什么不清楚。我希望结果表的行数尽可能少。所以:没有空值,除非值是真正不确定的。如果有多行具有相同的id和id_x值,这一定是因为表b和表c都有具有这些值的行。结果表应反映这些表数据中的每个关系/重叠,但仅此而已。您是否希望输入表中有空值?您的一些期望是否依赖于超级键的完全联接(UNIQUE NOT NULL)?表或联接是否有其他限制/约束?就投入而言,您的期望/预期结果是什么?请给出示例输入、查询以及预期/期望和实际输出。PS我怀疑没有这样的连接链是您想要的结果的查询。我怀疑你需要某些联合,而这在你的规范中起着很大的作用。试着描述并举例说明你想要2到3个表。你仍然不清楚你在GordonLinoff的答案上写的评论中想要什么。此外,“如果有多行带…”这表明,正如我在对你的问题的评论中假设的那样,你的情况涉及某些假设,但你没有给出它们。事情比你想象的要复杂。如果你想回答你的问题,不管是什么,请阅读并付诸行动,然后阅读并付诸行动。至少,给出一个输入和预期输出的例子。此外,评论不是为了澄清,请编辑您的问题。另外,请看我的答案。下面是如何“清楚表达”:请(1)给出PKs、UNIQUEs、NOT NULLs、FKs以及任何其他关于表一次可以容纳的内容的限制(无论是否声明)&(2)完成这句话(假设)∈" 类似于SQL“in”,但匹配相同值的列或同时匹配两个值的列(null):我希望行具有列(id,id\u x,name),其中[(id,id\u x)∈ (b联合体c)和((id,名称)在a中或(id)不在(从a中选择id)中且名称为空)或……(可能…)或(id)不在(从(b联合体c中选择id))和(id,名称)∈ a和id_x为空。