2017-05-19 3 views
1

null参照可能なReferenceId列を持つ自己参照表(項目)があります。これは、親(Type = 0)、および可能な子(Type = 1)を持つ最大2レベルの階層です。自己参照表のバッチ更新の実行

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

現在、表内の参照データは壊れています。私は小さなソフトウェアを書くことでリファレンスを回復することができますが、SQL(またはLinq)クエリを使用して単一のバッチで実行できるかどうかは疑問です。

何が行われる必要があるかを理解するために、Itemsとの1対多の関係を持つコンテナテーブルもあります。

だから、アイテムテーブルの重要な列は、ID、ContainerIDの、ReferenceIdになると入力します、私はあるに必要なもの

UPDATE Items SET Referenceid = ? 
FROM Items WHERE Type = 1 

?アイテムの親レコードのIDである必要があります。これは、子と同じコンテナにあります。

子供はコンテナに親レコードが1つしかない場合にのみ更新する必要があります。だから、

、私はこのような構造を持っている場合:

Id ContainerId  Referenceid  Type 
1  1    NULL    0 
2  1    NULL    0 
3  1    NULL    1 

を2つの親レコード(タイプ= 0)はコンテナID = 1(ID = 1、ID = 2であるので、私は更新を実行するべきではありません)。だから、

、私はこのような構造を持っている場合:

Id ContainerId  Referenceid  Type 
1  1    NULL    0 
2  1    NULL    1 
3  1    NULL    1 

を私はコンテナ内の唯一の1の親があるのでReferenceId = 1を設定し、ID = 2、ID = 3の両方を更新する必要があります。

これは明らかです。何かご意見は?

答えて

1

コンテナの親だけあるのみ親アイテムを取得するためにcommon table expressionを使用して、共通テーブル式でinner joinを使用して:項目についてhttp://rextester.com/CDOIN71171

;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デモ行:

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