当列不共享任何参数(包括主键)时,如何在 MS SQL Server 中进行 FULL OUTER JOIN?
Posted
技术标签:
【中文标题】当列不共享任何参数(包括主键)时,如何在 MS SQL Server 中进行 FULL OUTER JOIN?【英文标题】:How to do FULL OUTER JOIN in MS SQL Server when columns don't share any parameter including primary key? 【发布时间】:2020-09-12 01:44:47 【问题描述】:我有很多表(我们称它们为单参数表),其中包括 ID(主键)和另一个参数(每个表中有 2 列)。我希望将所有这些加入到一个由 ID 和 param_1、param_2、....、param_n 列组成的joined_table 中。对于 ID 列(主键),joined_table 不是 NULL,其他列是 Nullable。 当参数共享ID值时,我可以正常进行FULL OUTER JOIN,没有问题。但是当一个参数不与任何其他参数共享主键时,我就会遇到问题。 简单地说,假设对于 ID 124,第三个单参数表中的 param_3 有一些值,但在其他单参数表中没有其他出现和值。
我的代码如下:
Insert into [joined_table]
(ID, param_1,param_2,param_3)
SELECT
ID
,param1
,param2
,param3
FROM
(
SELECT
-- here if I write just "A.ID as ID" I will receive error of unfilled primary key column)
COALESCE( A.ID, B.ID, C.ID) as ID
, A.param_1 as param1
, B.param_2 as param2
, C.param_3 as param3
FROM
(
(SELECT ID, param_1 FROM single_param_table_1) A
FULL OUTER JOIN
(SELECT IِِD, param_2 FROM single_param_table_2) B on A.ID= B.ID
FULL OUTER JOIN
(SELECT ID, param_3 FROM single_param_table_3) C on A.ID = C.ID
-- or:
-- ISNULL(A.ID, B.ID)= C.ID
)
) as joined ;
我收到的错误信息如下:
Violation of PRIMARY KEY constraint 'PK_joined_table'. Cannot insert duplicate key in object 'joined_table'.
参数 3 似乎与其他参数没有完全分开,如果它共享密钥,则会尝试将重复的行插入到表中。
理想情况下,我希望得到 join_table 的结果:
ID | param 1 | param 2 | param 3
=======================================
123 | 11 | 12 | NULL
---------------------------------------
124 | NULL | NULL | 23
【问题讨论】:
选择所有可能的 ID 并将其加入您当前的查询(您应该使用分组排除重复项)。 @Iraj 。 . .您的问题不在于缺少 id 时。您的问题是joined_table
中已经有行,或者一个或多个表有重复。
@Arvo 感谢您的回复。左连接有助于避免错误,但是我不会有任何与最后一列相关的条目(与其他参数不共享任何公共主键的列/参数)
@GordonLinoff 谢谢!你救了我。问题在于最后一个 single_param_table 中有一个重复的 ID。我在我的选择语句中使用了 distinct,现在它已经解决了。 select distinct coalesce(t1.id, t2.id, t3.id, t4.id, . . . ) as id
这能回答你的问题吗? Strange duplicate behavior from GROUP_CONCAT of two LEFT JOINs of GROUP_BYs
【参考方案1】:
您的问题是一个或多个表有重复。
与此同时,您的 FULL JOIN
逻辑正在过滤掉您似乎想要的行。您可以简化和改进逻辑:
select coalesce(t1.id, t2.id, t3.id, t4.id, . . . ) as id,
t1.param as param1,
t2.param as param2,
t3.param as param3,
t4.param as param4,
. . .
from single_param_table_1 t1 full join
single_param_table_2 t2
on t2.id = t1.id full join
single_param_table_3 t3
on t3.id = coalesce(t1.id, t2.id) full join
single_param_table_4 t4
on t4.id = coalesce(t1.id, t2.id, t3.id) full join
. . .
也就是说,您需要大量使用coalesce()
,以便id
s 在表中匹配。
我应该注意到标准 SQL 和大多数数据库都支持 using
子句,它简化了这个逻辑。但是,SQL Server 不支持using
。
这简化了您的逻辑。但是,您的问题是一个或多个表具有重复的 ID。
【讨论】:
感谢您的回复。我实现了它,不幸的是仍然得到同样的错误。如果我使用 LEFT JOIN 而不是 FULL JOIN,我不会出错,但是当最后一个参数为 NULL 并且没有最后一个参数的值的行时,joined_table 结果将只包含第一个参数。 更新:我在选择ID之前添加了“distinct”,问题解决了!select distinct coalesce(t1.id, t2.id, t3.id, t4.id, . . . ) as id
,谢谢。
@Iraj 。 . .您在基础表中有重复项。如果select distinct
有效,则重复项对于另一列具有相同的值。
谢谢。是的,我在其中一个基础表中有重复项。 “不同”有助于跳过重复项。它可能只选择该重复 ID 的第一个条目。这有什么问题吗?如果它删除重复的 ID 我很好(无论其他参数的值是什么)
@Iraj 。 . .没问题——除非你应该弄清楚为什么会有重复,如果有问题就修复它。我的评论是,不仅id
重复,而且id
/param
重复。以上是关于当列不共享任何参数(包括主键)时,如何在 MS SQL Server 中进行 FULL OUTER JOIN?的主要内容,如果未能解决你的问题,请参考以下文章