【发布时间】:2017-07-19 16:40:49
【问题描述】:
我正在使用 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);
我想要/期望的很难说清楚,但基本上,我想要一个“完整的”完全合并。除非不可避免,否则我不希望任何地方出现空字段。
例如,每当有一个非空 id 时,我希望相应的名称列始终具有 name_a 并且不为空。相反,其中一个示例查询返回半冗余结果,其中一行具有 name_a 但没有 id,另一行具有 id 但没有 name_a,而不是单个合并行。
当连接以其他顺序列出时,我确实得到了想要的结果(但我不确定可能会出现什么其他问题,因为未来的数据是未知的)。
【问题讨论】:
-
您是否期望输入表中可能存在 NULL?您的某些期望是否取决于超级键上的 FULL JOIN(UNIQUE NOT NULL)?表或连接是否有任何其他限制/约束?就输入而言,您期望/预期的结果究竟是什么?请给出示例输入、查询以及预期/期望和实际输出。 PS我怀疑没有这样的连接链是你想要的结果的查询。我怀疑您需要某些工会,并且 OR 在您的规范中起着重要作用。尝试描述并举例说明您想要 2 个然后 3 个表的内容。
-
您仍然不清楚您在 GordonLinoff 的回答中写的 cmets 中想要什么。此外,“如果有多行...”正如我在对您的问题的评论中假设的那样,您的情况涉及某些假设但您没有给出它们。事情比你想象的要复杂。如果您想回答您的问题,无论它是什么,请阅读并在minimal reproducible example 上采取行动,然后阅读并根据我的评论采取行动。至少,给出输入和预期输出的例子。另外, cmets 不是为了澄清,请编辑您的问题。另外,请参阅我的答案。
-
这里是如何“表达”:请 (1) 给出 PK、UNIQUE、NOT NULL、FK 以及任何其他限制您的表一次可以容纳的内容(无论是否声明)&( 2)完成这句话(假设“∈”就像SQL“in”但匹配相同值或两者都为null的列):我想要具有列(id,id_x,name)的行,其中[(id,id_x)∈(b联合c) and ((id,name) in a or (id) not in (select id from a) and name is null)] or ... 。也许 ... 或 (id) 不在 (select id from (b union c)) 和 (id,name) ∈ a 并且 id_x 为空。
标签: sql postgresql null outer-join associativity