在自引用表中执行批量更新

时间:2017-05-19 14:59:24

标签: sql-server linq tsql linq-to-entities

我有一个带有可空的ReferenceId列的自引用表(Items)。这是一个最大的两级层次结构,父级(Type = 0)和可能的子级(Type = 1)。

Example of Items Parent record: ReferenceId = null  Type = 0
Example of Items Child record: ReferenceId = Id of Parent   Type = 1

目前表中的参考数据已被破坏。我可以通过编写一个小软件来恢复引用,但我想知道我是否可以使用SQL(或Linq)查询在一个批处理中执行它。

要了解需要做什么,还有一个容器表,它与Items有1对多的关系。

因此,Items表中的重要列将是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个父级。

我希望这很清楚。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

使用common table expression仅获取容器的唯一父项,然后使用带有公用表表达式的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)

返回:

+----+-------------+-------------+------+
| 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 |
+----+-------------+-------------+------+