2017-10-19 90 views
0

我有一個SQL Server查詢,它返回一個數據集,顯示一個人的ID,該人工作的實體,屬於該實體的位置,分配給該案例的協調員和人的地位。從SQL Server數據集中刪除特定記錄的窗口函數

ID EntityName  LocationName  AssignedTo  StatusName 
    17  F&S   St. Lucie   A Hardon  Active 
    17  F&S   St. Lucie   A Hardon  Withdrawn 
    18  F&S   NH    A Hardon  Withdrawn 
    20  H&H   NCH    B Reedy  Active 

我需要消除EntityName,LocationName和AssignedTo組合的唯一狀態爲Withdrawn的記錄。所以在上面的數據集中,我想要用LocationName = NH刪除ID = 18。

我使用窗口函數,這可能是在正確的道路上嘗試,但我不知道如何着手:

Select id, entityname, locationname, assignedto, statusname 
    Into #test 
    From Table A 

    Select *, 
      row_number()over(partition by entityname, locationname, assignedto 
          order by case when statusname = 'Withdrawn' then 1 
            else 2 end) as rn 
    from #test 

這給了我這樣一個結果:

ID EntityName LocationName  AssignedTo  StatusName  RN 
    17  F&S   St. Lucie  A Hardon  Withdrawn  1 
    17  F&S   St. Lucie  A Hardon  Active   2 
    18  F&S   NH    A Hardon  Withdrawn  1 
    20  H&H   NCH    B Reedy  Active   1 

但現在我被困在如何繼續,或者如果我甚至以這種錯誤的方式去做。

+0

'StatusName'可以是其他值嗎? –

+0

是的,有7個狀態,但我需要刪除的唯一一個是撤回。 – jackstraw22

回答

2

想想這個略有不同的方式。計數是而不是撤回的數字。如果這是0,則全部撤回。

適當的窗函數是有條件的聚集,而不是排名函數:

select t.* 
from (Select t.*, 
       sum(case when statusname <> 'Withdrawn' then 1 else 0 end) over 
        (partition by entityname, locationname, assignedto) as num_notwithdrawn 
     from #test t 
    ) t 
where num_notwithdrawn = 0; 
+0

當我嘗試這樣做時,它幾乎消除了所有記錄(約1,000),並且只保留了2,兩者都是狀態='撤回。「 – jackstraw22

+0

@ jackstraw22。。'statusname'曾經'NULL'? –

0
Select id, entityname, locationname, assignedto, statusname, 
    r row_number()over(partition by entityname, locationname, assignedto 
        order by CASE statusname WHEN 'Withdrawn' THEN 1 ELSE 2 END) as rn Into #test From Table A 
Select * from #test LEFT OUTER JOIN 
    (
     SELECT MAX(rn) MRNO,ID FROM #test GROUP BY ID 
) T ON T.ID = #TEST.ID WHERE rn = MRNO AND statusname ='Withdrawn' 

這將eliinate與實體名稱,LOCATIONNAME的組合單獨撤銷狀態行,assignedto

+0

這不會消除所有不是='撤回'的狀態? – jackstraw22

+0

編輯查詢 –

0

刪除用INNER JOIN

DELETE T 
FROM Table T 
INNER JOIN 
(
    SELECT EntityName,LocationName,AssignedTo 
    FROM Table 
    WHERE StatusName='Withdrawn' 
    GROUP BY EntityName,LocationName,AssignedTo 
    HAVING COUNT(*) = 1 
)D ON D.EntityName=T.EntityName AND D.LocationName=T.LocationName AND D.AssignedTo=T.AssignedTo 
+0

我試了左連接 - 它很接近,但沒有工作。有幾個例子,一個人的ID可以屬於多個位置的實體。如果其中一個實體只有一條記錄,並且該記錄='撤回',那麼該人的所有其他記錄也將被刪除。ID = 112,實體= F&S,​​位置= NE佛羅里達州,狀態=撤銷。被刪除,因爲它應該是,但ID = 112的所有其他記錄也被消除。 – jackstraw22

+0

是的,那麼你不能使用ID。我認爲這是一個身份專欄,但是,它重複。您必須刪除MAX(ID),然後通過外部查詢中的字段加入這三個組,以使其發揮作用,但是,如果這三個字段沒有編入索引,那麼這可能會對大型數據集產生性能影響。 –

+0

我更新了非標識符字段上的連接。 –

0

試試bel嗷嗷之一:

WITH CTE 
AS (
Select id, entityname, locationname, assignedto, statusname, 
     row_number()over(partition by entityname, locationname, assignedto 
         order by statusname) as rn 
    From Table A) 
DELETE from CTE where rn=1 and statusname = 'Withdrawn' 
2

嘗試使用EXISTS

Select * 
FROM #test t1 
WHERE EXISTS (SELECT * 
       FROM #test t2 
       WHERE t1.EntityName = t2.EntityName 
         and t1.LocationName = t2.LocationName 
         and t1.AssignedTo = t2.AssignedTo 
         and t2.StatusName <> 'Withdrawn') 
+0

我覺得這樣做了!但我很困惑,爲什麼它會起作用。爲什麼這不會消除所有「撤回」狀態? – jackstraw22

+0

Exists正在查看EntityName,LocationName,AssignedTo的組合是否存在於狀態不是Withdrawn的表中。因此,對於第一條記錄,它需要F&S,St. Lucie和A Hardon在這個組合中搜索除了Withdrawn之外的任何狀態。恰好如此,它發現了第一個記錄(它自己),它是活動的,所以它保留了它。對於第二個記錄,它也找到了自這些字段匹配以來的第一個記錄並保持第二行..它就像使用IN()過濾器,但允許您查找多個字段,而不是隻有一個 – JamieD77

+0

它花了我一段時間,但我想我理解它正在尋找第一個表中的所有記錄它們在3個字段上匹配,但在第二個表中沒有status ='Withdrawn',這會從第一個表中返回所有記錄,包括'Withdrawn',因爲實際上並沒有從第一個表中過濾。唯一的記錄表2中的d是'撤回',它將從表2中過濾掉,因此不能加入到表1中。 – jackstraw22

0

爲什麼不能識別使用內部連接的潛力刪除,然後添加一個簡單的WHERE刪除「撤回」條款項?

delete from #table a 
inner join (
      select entityname, locationname, assignedto, count(*) 
      from #table 
      group by entityname, locationname, assignedto 
      having count(*) = 1) b 
      on b.entityname = a.entityname 
      and b.locationname = a.locationname 
      and b.assignedto = a.assignedto 
where a.statusnname = 'Withdrawn' 

內加入保持「勢」缺失(E,L的任意組合和一個只用一個記錄),並WHERE子句刪除相應的記錄(多個)後續的。