2017-11-10 4 views
0

私はすべてのレコードを削除しようとしていますが、練習とエンティティの組み合わせが1回しか表示されず、1つのレコードのステータスがTerminatedまたはWithdrawnの場合、削除したい。練習/実体が複数のレコードを持ち、それらのレコードの少なくとも1つがTerminated/Withdrawn以外のステータスである場合、それらの他のレコードを保持したい。私はこれを行うクエリを書いたが、これは以下の通りである。NOT INを使用したNULL値の問題

しかし、問題は、クエリがNULLレコードを削除していることです。私はこれがExists/NOT IN句のためにあることを理解しています。ここでNULL <>(Terminated、Withdrawn)はUNKNOWNと評価されます。

NOT EXISTS/INを使用して逆の方法でクエリを作成しようとしましたが、何千もの他のレコードが削除されました。誰もこの状況でNULL値を含める方法を知っていますか?

declare @tab Table 
    (practice varchar(100), 
    entity varchar(100), 
    assignedto varchar(100), 
    statusname varchar(50) 
    ) 
    insert into @tab values ('F&S', 'Sinai', 'AnnM', NULL); 
    insert into @tab values ('F&S', 'Levin', 'AnnM', NULL); 
    insert into @tab values ('F&S', 'Hopkins','AnnM', NULL); 

    select *, 
    ROW_NUMBER()over(partition by entity, statusname order by entity) as rn 
    from @tab t1 
    where exists(select * 
       from @tab t2 
       where t1.practice = t2.practice 
       and t1.entity= t2.entity 
       and t1.assignedto = t2.assignedto 
       and t2.statusname not in('Withdrawn', 'Terminated')); 
+2

非常識な方法: '(t2.statusnameないで( '撤回'、 '終端')またはt2.statusnameがNULLではありません)非常識な何もありません' – LONG

+1

@LONG。正しい方法でなければなりません。 –

+0

@JuanCarlosOropeza、haha、 'ISNULL'などを使って怠けているようです。xDの下に投稿された回答と同じです。 – LONG

答えて

1

あなたはダミーの値でISNULLを使用することができます。私はむしろそうオプティマイザはまだどのインデックスを使用することができますt2.statusname IS NULLを使用

select *, 
ROW_NUMBER()over(partition by entity, statusname order by entity) as rn 
from @tab t1 
where exists(select * 
      from @tab t2 
      where t1.practice = t2.practice 
      and t1.entity= t2.entity 
      and t1.assignedto = t2.assignedto 
      and ISNULL(t2.statusname, '@@@') 
       not in('Withdrawn', 'Terminated')); 

Rextester.com

+0

' t2.statusname IS NOT NULL'が優れています。インデックスを使用することができます –

+0

@JuanCarlosOropeza一般的にはい(** SARGableカウント** :))。それでもOPの例ではテーブル変数がありますので問題ありません – lad2025

+1

* ISNULLは使用しないでください。 'IS NOT NULLであり、ステータス名ではない'はインデックスを利用することができます。一方、 'ISNULL(...)'は結果を計算するために全テーブルスキャンを強制します –

2

select *, 
     ROW_NUMBER()over(partition by entity, statusname order by entity) as rn 
from @tab t1 
where exists(select 1 
      from @tab t2 
      where t1.practice = t2.practice 
       and t1.entity= t2.entity 
       and t1.assignedto = t2.assignedto 
       and (t2.statusname IS NULL OR 
        t2.statusname not in ('Withdrawn', 'Terminated') 
        ) 
      ); 
+2

AND NOT(t2.statusname in( 'Withdrawn'、 'Terminated'))は、同じコードの短いバージョンになります –

+0

これはうまくいくようです。私は思ったよりずっと簡単です。 – jackstraw22