2016-11-23 4 views
1

私は次のようにSQL Server 2008でテーブル#tempを持っている:レコードにp_id値が等しい、h_id値は(100と300を確認してください)に等しくなければならないことに注意してください現在のデータとお互いの一致条件に基づいてフィールドの値を更新するにはどうすればよいですか?

Id p_id h_id ProvincialPID 
1 100 A1256  null 
2 200 A7865  null 
3 300 A5555  null 
4 100 A1256  null 
5 300 A5555  null 
6 400 A7865  null 
... 

!一方、p_idの値は等しくないが、h_idの値が等しいレコードがある(200と400のように)! 、レコードのp_idは、他のものと一致するが、そのh_idマッチ少なくとも一つの他のいない場合は、レコードのp_idは、別のレコードのp_id、その後ProvincialPID = p_id、それ以外のマッチングされている場合:私が欲しいもの

があるという事実に基づいてProvincialPID列を更新することですその後、ProvincialPID = h_id

例:上記のサンプルデータでは、私が見ることになっています:

Id p_id h_id ProvincialPID 
1 100 A1256  100 
2 200 A7865  A7865 
3 300 A5555  300 
4 100 A1256  100 
5 300 A5555  300 
6 400 A7865  A7865 
... 

次のコードは、私はそれを実行するのに役立っています。しかし、それは非常に遅く、私はより効率的なコードを適用したいと思います。しかし、私はそれをより効率的にする方法を見つけることができませんでした。どんな助け/助言も非常に高く評価されます。

DECLARE @counter INT = 0; 
DECLARE @currentPID varchar(50); 
DECLARE @currentID varchar(50); 
DECLARE @currentHID varchar(50); 

WHILE @counter < (select COUNT(*) from #temp) 
BEGIN 
    set @currentID = (select top (1) x.Id from (select top(@counter) * from #temp order by Id desc) x) 
    set @currentPID = (select top (1) x.p_id from (select top(@counter) * from #temp order by Id desc) x) 
    set @currentHID = (select top (1) x.h_id from (select top(@counter) * from #temp order by Id desc) x) 

    if((select COUNT(*) from #temp t where t.Id != @currentID and t.p_id = @currentPID) > 0) 
     update #temp 
     set ProvincialPID = @currentPID 
     where Id = @currentID 
    else if ((select COUNT(*) from #temp t where t.Id != @currentID and t.p_id != @currentPID and t.h_id = @currentHID) > 0) 
     update #temp 
     set ProvincialPID = @currentHID 
     where Id = @currentID 

    SET @counter = @counter + 1; 
END; 

答えて

1

オーケー最初のいくつかの一般的なアドバイス - あなたは、あなたがこれまで自分がループしながらやって、またはSQLでカーソルを使用して発見した場合おそらくそれを間違っている。あなたはそれらをほとんど必要としません。代わりに、クエリを作成して必要なデータセットを取得し、変更を一括してセット全体に適用することについて考えてみてください。

私はあなたが必要と思うものは...少なくともあなたのためのデータの例です。

create table #temp 
(
    Id int, 
    p_id int, 
    h_id varchar(5), 
    ProvincialPID varchar(5) 
); 

insert into #temp(Id, p_id, h_id) values(1,100,'A1256'); 
insert into #temp(Id, p_id, h_id) values(2,200,'A7865'); 
insert into #temp(Id, p_id, h_id) values(3,300,'A5555'); 
insert into #temp(Id, p_id, h_id) values(4,100,'A1256'); 
insert into #temp(Id, p_id, h_id) values(5,300,'A5555'); 
insert into #temp(Id, p_id, h_id) values(6,400,'A7865'); 

update #temp 
set ProvincialPID = p_id 
where p_id in (select p_id from #temp group by p_id having count(*) > 1) 

update #temp 
set ProvincialPID = h_id 
where p_id not in (select p_id from #temp group by p_id having count(*) > 1) 
and h_id in (select h_id from #temp group by h_id having count(*) > 1) 

select * from #temp 
0

私は2つの更新、p_id用とh_id用としてこれを行うだろう:あなたは、このようなレコードは持っている場合など、不足しているいくつかのユースケースを有していてもよく、データによっては

update t 
    set ProvincialPID = p_id 
    from #temp t 
    where exists (select 1 
        from #temp t2 
        where t2.p_id = t.p_id and t2.id <> t.id 
       ); 

update t 
    set ProvincialPID = h_id 
    from #temp t 
    where exists (select 1 
        from #temp t2 
        where t2.h_id = t.h_id and t2.id <> t.id 
       ) and 
      ProvincialPID is NULL; 
0
;WITH cte AS (
    SELECT 
     Id 
     ,COUNT(*) OVER (PARTITION BY p_id, h_id) as MatchBothCount 
    FROM 
     #temp t 
) 

UPDATE t 
    SET ProvincialPID = CASE 
       WHEN c.MatchBothCount > 1 THEN CAST(t.p_id AS VARCHAR(5)) 
       ELSE t.h_id 
      END 
FROm 
    #temp t 
    INNER JOIN cte c 
    ON t.Id = c.Id 
WHERE 
    t.ProvincialPID IS NULL 

まったく一致しないか、または3レコードがh_idと一致しますが、3つのレコードのうち2つだけがp_idと一致します。その未知数に基づいて、同じp_id、h_idの組み合わせで1つ以上のレコードがあるかのように解釈し、p_idを使用します。使用しない場合はh_idを使用します。ウィンドウ関数に単純なカウント(*)を使用すると、そこに到達するのに役立ちます。

それとも、存在するメソッドを使用しますが、まだのような一つの操作でそれを行うことができます:

UPDATE t 
    SET ProvincialPID = CASE WHEN EXISTS (
          SELECT 1 
          FROM #temp t2 
          WHERE 
          t.p_id = t2.p_id 
          AND t.h_id = t2.h_id 
          AND t.Id <> t2.Id) 
         THEN CAST(t.p_id AS VARCHAR(5)) 
         ELSE t.h_id END 
FROM 
    #temp t 
WHERE 
    ProvincialPID IS NULL 
関連する問題