【发布时间】:2021-09-23 17:10:24
【问题描述】:
我遇到了一个有点令人困惑的问题。
简化查询:(假设ID是每个表的主键)
SELECT
A.ID,
A.Data,
B.Data,
C.Data
FROM
A FULL OUTER JOIN
B ON A.ID = B.ID FULL OUTER JOIN
C ON A.ID = C.ID
我使用FULL OUTER JOIN's 因为在我的情况下,不能保证任何ID 在所有三个表中,但如果它在多个表中,我想查看它的所有数据排成一排。
这是我很快意识到的问题:如果B 和C 两个表中都有一个ID(但不是A),那么您会遇到以下问题:
-
ID字段是NULL,用于未出现在表A中的ID。这是有道理的,因为查询选择了A.ID。我找到了一个非常简单的方法,那就是使用COALESCE(即COALESCE(A.ID,B.ID,C.ID))。 -
不在表
A中的ID的数据在两个单独的行中返回。 (一行有NULL's forB's data,另一行有NULL's forC's data。)想了想,这也是有道理的,因为上面的查询方式是写的。B和C两个表都基于表A连接,因此如果ID不在表A中,则查询与表ID中的ID连接没有关系B和C。我也找到了解决这个问题的方法,即在ON子句中明确指定与它之前的每个 表的关系,以OR分隔。
因此进行以下更改将解决这两个问题:
SELECT
COALESCE(A.ID,B.ID,C.ID),
A.Data,
B.Data,
C.Data
FROM
A FULL OUTER JOIN
B ON A.ID = B.ID FULL OUTER JOIN
C ON A.ID = C.ID OR B.ID = C.ID
这很好用,但我花了一些时间才弄清楚这一点,以后遇到此查询的人员可能会很奇怪,因为在ON 子句中使用了COALESCE 和一堆OR乍一看似乎是多余的,但实际上两者都需要。
这对于较大的查询也可能会变得非常混乱,因为ON 子句的大小对于以这种方式连接的每个表来说都是复合的。
我的问题是:是否有其他内置方式或其他技巧来处理这种类型的 OUTER JOIN 已经考虑到这些您不需要为 INNER JOIN 考虑的额外条件s?
【问题讨论】:
-
不,没有“内置方式”。不,我们不应该寻求“技巧”。您所描述的通常是外部联接的结果-而不仅仅是完全联接。 IME 使用
通常很少见,但我确实看到许多奇怪的或“冗长的”或“难以编写/解释”的查询,这些查询是架构受损的结果。在这里可以说你有 3 个不同的实体(表)代表同一个“事物”——一个规范化问题。 -
@SMor 谢谢,我不一定是在寻找“技巧”,我对当前的方式没意见,只是想知道是否还有其他方式,因为我发现这种策略特别不寻常。但是,是的,我同意这种类型的查询通常很少见,在这种情况下,三个表可能是同一个“东西”。不幸的是,在这种情况下,没有一个包含所有 ID 列表的“主”表,我意识到这通常是这种情况。这是我遇到的第一种情况并非如此。
-
是的 - 有时模式会迫使我们在编写查询时手动生成有用的信息。但正如我所写,这通常是外连接的产物,是查询编写者需要理解和解决的问题。
-
我相信另一种方法是通过每个表的键加入 A->B、A->C、B->C 组,并从每个表中选择 hte 最大值。将通过聚合消除每个键的重复项..我需要样本数据来测试它..或者可能基于键的数据来 PIVOT 数据....没有键,没有枢轴数据;但列仍会旋转...只要至少 1 个表有 1 条记录。
-
是的,还有另一种方法 -
UNION ALL三个表。在 UNION ALL 之外,按键分组并使用各种聚合函数将 1-3 行归结为 1。仅当您感兴趣的列的完整列表在所有表中匹配时才有效
标签: sql-server sql-server-2008 outer-join