2017-05-19 5 views
1

nullable ReferenceId 열이있는 자체 참조 테이블 (항목)이 있습니다. 상위 (유형 = 0) 및 가능한 하위 (유형 = 1)가있는 최대 2 레벨 계층 구조입니다.자체 참조 테이블에서 일괄 업데이트 수행

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

현재 테이블의 참조 데이터가 손상되었습니다. 작은 소프트웨어를 작성하여 참조를 복구 할 수 있지만 SQL (또는 Linq) 쿼리를 사용하여 단일 배치에서 수행 할 수 있는지 궁금합니다.

수행해야 할 작업을 이해하기 위해 항목과 1 대 다수 관계가있는 컨테이너 테이블도 있습니다.

그래서, 항목 테이블에서 중요한 열 이드, ContainerId, ReferenceId을하고 입력합니다 I이 필요가있는 무엇

:

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

? 하위 항목과 동일한 컨테이너에있는 항목 상위 항목 레코드의 ID 여야합니다.

그리고 컨테이너에 부모 레코드가 하나만있는 경우에만 자식을 업데이트해야합니다.

그래서,이 같은 구조가있는 경우 : 용기 아이디 = 1 (ID = 1과 식 2의 두 부모 기록 (유형 = 0)가 있기 때문에

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

내가 업데이트를 수행하지 않아야을). 나는이 같은 구조가있는 경우

그래서 : 나는 두 식 (2)와 식 (3)을 업데이트해야합니다

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

, ReferenceId = 1 설정을 용기 만 한 부모가 있기 때문이다.

분명히하는 것이 좋겠습니다. 이견있는 사람?

답변

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