Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何编写SQL查询以将三重多对一关系插入到多对多关系?_Sql_Sql Server_Sql Server 2008_Many To Many_Sql Server 2008 R2 - Fatal编程技术网

如何编写SQL查询以将三重多对一关系插入到多对多关系?

如何编写SQL查询以将三重多对一关系插入到多对多关系?,sql,sql-server,sql-server-2008,many-to-many,sql-server-2008-r2,Sql,Sql Server,Sql Server 2008,Many To Many,Sql Server 2008 R2,I以下两个表/列: TableA id | data TableB fkeyA1 | fkeyA2 | fkeyA3 | name TableB中的前三列是外键,都指向TableA。我想将表B转换为以下两个表: TableC id | name TableD fkeyC | fkeyA 所以表B中的一行变成表C中的一行加上表D中的三行。我应该如何为此编写SQL查询 编辑: 在表格B中,在(fkeyA1,fkeyA2,fkeyA3)上有一个唯一的索引,但是名称列不一定有唯一的值。我首先在表

I以下两个表/列:

TableA
id | data

TableB
fkeyA1 | fkeyA2 | fkeyA3 | name
TableB中的前三列是外键,都指向TableA。我想将表B转换为以下两个表:

TableC
id | name

TableD
fkeyC | fkeyA
所以表B中的一行变成表C中的一行加上表D中的三行。我应该如何为此编写SQL查询

编辑:
表格B
中,在
(fkeyA1,fkeyA2,fkeyA3)
上有一个唯一的索引,但是
名称
列不一定有唯一的值。

我首先在表格C中插入
Id
作为
标识的列

INSERT INTO TableC(name)
SELECT b.name
FROM TableB AS b
然后我会写一篇插页:

SELECT c.Id, b.fkeyA1
FROM TableC AS c
INNER JOIN tableB AS b ON c.name = b.name
UNION    
SELECT c.Id, b.fkeyA2
FROM TableC AS c
INNER JOIN tableB AS b ON c.name = b.name
UNION
SELECT c.Id, b.fkeyA3
FROM TableC AS c
INNER JOIN tableB AS b ON c.name = b.name
插入表格的另一种方法是:

SELECT c.Id, a.Id
FROM TableB AS b
INNER JOIN TableC AS c ON b.name = c.name
LEFT JOIN TableA AS a ON b.fkeyA1 = a.Id
   OR b.fkeyA2 = a.Id
   OR b.fkeyA3 = a.Id
如果tableB包含名称“Adam”两次,则来自B的两条记录将由TableC中的同一Id引用,TableD将有6条该Id的记录

例如


您可以使用游标语句:

declare @idC table(id int)
declare @fkeyC int, @fkeyA1 int, @fkeyA2 int, @fkeyA3 int, @name varchar(8)
declare CursorB cursor fast_forward for select fkeyA1, fkeyA2, fkeyA3, name from TableB
open CursorB
fetch next from CursorB into @fkeyA1, @fkeyA2, @fkeyA3, @name
while @@fetch_status = 0
begin
    insert into TableC(name) output inserted.id into @idC values (@name)
    set @fkeyC = (select top 1 id from @idC)
    insert into TableD(fkeyC, fkeyA) values (@fkeyC, @fkeyA1), (@fkeyC, @fkeyA2), (@fkeyC, @fkeyA3)
    delete from @idC
    fetch next from CursorB into @fkeyA1, @fkeyA2, @fkeyA3, @name
end
close CursorB
deallocate CursorB

这可能不是性能最好的,但会允许名称列的值不唯一。

从逻辑上讲,我认为不需要嵌套
COALESCE()
——不管怎样,我认为您的意思是
在b.fkeyA1=a.Id或b.fkeyA2=a.Id或b.fkeyA3=a.Id上以a的形式左联接表a
,我相信你当前的版本会得到一些奇怪的结果…关于我的
LEFT JOIN
需要在表B上的问题,你完全正确,谢谢。但是,我不确定您不需要嵌套
COALESCE()
是什么意思。第一种方法是,如果您将
UNION ALL
更改为UNION
,则应适用于名称的重复值。我不知道我的第二种方法,我不在sql server附近进行测试。我将在UTC上午5:00附近查看一下,然后做出响应。
COALESCE()
是一个接受参数列表的函数,没有理由这样分割它。嵌套时也没有逻辑结果差异-
a1
始终是首选,无论
a2
a3
的状态如何。另外,b.fkeyA3=a1.id上的表A为a3?我想你的加入会有点混乱
a2
a3
将交叉连接-您不需要再连接到
TableA
两次-用
条件替换剩下的两列(并更新
COALESCE()
),您应该很好。@X-Zero我不知道COALESCE使用了两个以上的参数。原始联接的目标是分别为a1、a2和a3,但使用带有
ON
子句的联接更好。感谢今晚教我一两件事:)TableB中两个具有相同
名称的用户是否对应TableC中的相同Id?
declare @idC table(id int)
declare @fkeyC int, @fkeyA1 int, @fkeyA2 int, @fkeyA3 int, @name varchar(8)
declare CursorB cursor fast_forward for select fkeyA1, fkeyA2, fkeyA3, name from TableB
open CursorB
fetch next from CursorB into @fkeyA1, @fkeyA2, @fkeyA3, @name
while @@fetch_status = 0
begin
    insert into TableC(name) output inserted.id into @idC values (@name)
    set @fkeyC = (select top 1 id from @idC)
    insert into TableD(fkeyC, fkeyA) values (@fkeyC, @fkeyA1), (@fkeyC, @fkeyA2), (@fkeyC, @fkeyA3)
    delete from @idC
    fetch next from CursorB into @fkeyA1, @fkeyA2, @fkeyA3, @name
end
close CursorB
deallocate CursorB