正在自引用中执行批量更新 table
Performing batch update in self referencing table
我有一个自引用的 table(项目),其中有一个可为空的 ReferenceId 列。这是最大两级层次结构,具有父级 (Type = 0) 和可能的子级 (Type = 1)。
Example of Items Parent record: ReferenceId = null Type = 0
Example of Items Child record: ReferenceId = Id of Parent Type = 1
目前 table 中的参考数据已损坏。我可以通过编写一个小软件来恢复引用,但我想知道我是否可以使用 SQL(或 Linq)查询来一次性完成它。
要了解需要做什么,还有一个Containertable,它和Items是一对多的关系
因此,项目 table 中的重要列将是 Id、ContainerId、ReferenceId 和 Type
我需要的是:
UPDATE Items SET Referenceid = ?
FROM Items WHERE Type = 1
?应该是 Items 父记录的 ID,它与子记录在同一个容器中。
只有当容器中只有 1 个父记录时,子项才应该更新。
所以,如果我有这样的结构:
Id ContainerId Referenceid Type
1 1 NULL 0
2 1 NULL 0
3 1 NULL 1
我不应该执行更新,因为容器 Id=1(Id=1 和 Id=2)中有两个父记录(Type=0)。
所以,如果我有这样的结构:
Id ContainerId Referenceid Type
1 1 NULL 0
2 1 NULL 1
3 1 NULL 1
我应该同时更新 Id=2 和 Id=3,设置 ReferenceId = 1,因为容器中只有 1 个父级。
我希望这是清楚的。有什么想法吗?
使用 common table expression 仅获取容器唯一父项的那些父项,然后使用具有通用 table 表达式的 inner join
:
;with p as (
select
Id = min(Id)
, ContainerId
from Items p
where [Type] = 0
group by ContainerId
having count(*) = 1 /* <-- containers with only 1 parent */
)
update c
set c.ReferenceId = p.Id
from Items c
inner join p
on c.ContainerId = p.ContainerId
where c.Type = 1;
rextester 演示:http://rextester.com/CDOIN71171
项目行:
(1,1,null,0) /* <-- 1 parent in container 1 */
,(2,1,null,1)
,(3,1,null,1)
,(4,2,null,0) /* <-- 2 parents in container 2 */
,(5,2,null,0)
,(6,2,null,1)
returns:
+----+-------------+-------------+------+
| id | containerid | referenceid | type |
+----+-------------+-------------+------+
| 1 | 1 | NULL | 0 |
| 2 | 1 | 1 | 1 |
| 3 | 1 | 1 | 1 |
| 4 | 2 | NULL | 0 |
| 5 | 2 | NULL | 0 |
| 6 | 2 | NULL | 1 |
+----+-------------+-------------+------+
我有一个自引用的 table(项目),其中有一个可为空的 ReferenceId 列。这是最大两级层次结构,具有父级 (Type = 0) 和可能的子级 (Type = 1)。
Example of Items Parent record: ReferenceId = null Type = 0
Example of Items Child record: ReferenceId = Id of Parent Type = 1
目前 table 中的参考数据已损坏。我可以通过编写一个小软件来恢复引用,但我想知道我是否可以使用 SQL(或 Linq)查询来一次性完成它。
要了解需要做什么,还有一个Containertable,它和Items是一对多的关系
因此,项目 table 中的重要列将是 Id、ContainerId、ReferenceId 和 Type
我需要的是:
UPDATE Items SET Referenceid = ?
FROM Items WHERE Type = 1
?应该是 Items 父记录的 ID,它与子记录在同一个容器中。
只有当容器中只有 1 个父记录时,子项才应该更新。
所以,如果我有这样的结构:
Id ContainerId Referenceid Type
1 1 NULL 0
2 1 NULL 0
3 1 NULL 1
我不应该执行更新,因为容器 Id=1(Id=1 和 Id=2)中有两个父记录(Type=0)。
所以,如果我有这样的结构:
Id ContainerId Referenceid Type
1 1 NULL 0
2 1 NULL 1
3 1 NULL 1
我应该同时更新 Id=2 和 Id=3,设置 ReferenceId = 1,因为容器中只有 1 个父级。
我希望这是清楚的。有什么想法吗?
使用 common table expression 仅获取容器唯一父项的那些父项,然后使用具有通用 table 表达式的 inner join
:
;with p as (
select
Id = min(Id)
, ContainerId
from Items p
where [Type] = 0
group by ContainerId
having count(*) = 1 /* <-- containers with only 1 parent */
)
update c
set c.ReferenceId = p.Id
from Items c
inner join p
on c.ContainerId = p.ContainerId
where c.Type = 1;
rextester 演示:http://rextester.com/CDOIN71171
项目行:
(1,1,null,0) /* <-- 1 parent in container 1 */
,(2,1,null,1)
,(3,1,null,1)
,(4,2,null,0) /* <-- 2 parents in container 2 */
,(5,2,null,0)
,(6,2,null,1)
returns:
+----+-------------+-------------+------+
| id | containerid | referenceid | type |
+----+-------------+-------------+------+
| 1 | 1 | NULL | 0 |
| 2 | 1 | 1 | 1 |
| 3 | 1 | 1 | 1 |
| 4 | 2 | NULL | 0 |
| 5 | 2 | NULL | 0 |
| 6 | 2 | NULL | 1 |
+----+-------------+-------------+------+