2016-12-13 133 views
0

這可能有一個明顯的解決方案,但我不記得此刻該怎麼稱呼它。通過首選排序過濾列表

假設你有一個表是這樣的:

Member | ID  | Type 
------ | ------ | ------ 
100 | 1  | A 
100 | 2  | B 
101 | 3  | A 
102 | 4  | A 
103 | 5  | B 
104 | 6  | B 
104 | 7  | A 
104 | 8  | A 

如果成員有一個我想與該成員的回報所有行。
如果一個成員沒有A,那麼我想返回所有包含該成員的B的行。

我意識到我可以使用NOT EXISTS編寫解決方案,但我想知道是否有更通用的解決方案(在多個類別的情況下)。基本上我想按照首選順序來篩選一個類別是否存在。

在這個例子中,結果將返回:

Member | ID  | Type 
------ | ------ | ------ 
100 | 1  | A 
101 | 3  | A 
102 | 4  | A 
103 | 5  | B 
104 | 7  | A 
104 | 8  | A 

感謝。

回答

2
Declare @YourTable table (Member int,ID int,[Type] varchar(25)) 
Insert Into @YourTable values 
(100 , 1 , 'A'), 
(100 , 2 , 'B'), 
(101 , 3 , 'A'), 
(102 , 4 , 'A'), 
(103 , 5 , 'B'), 
(104 , 6 , 'B'), 
(104 , 7 , 'A'), 
(104 , 8 , 'A') 

Select Member,ID,Type 
From (
     Select * 
       ,RN = Dense_Rank() over (Partition By Member Order by Type) 
      From @YourTable 
    ) A 
Where RN=1 

返回

Member ID Type 
100  1 A 
101  3 A 
102  4 A 
103  5 B 
104  7 A 
104  8 A 
+0

這似乎這樣的伎倆。我以前沒有聽說過dense_rank()。謝謝! – JJ32

+0

@ JJ32窗口函數是我們的朋友。值得花時間去適應他們。乾杯。 –

0

你可以試試這個:

 ;WITH tb(Member,ID ,Type)AS 
    (
     SELECT 100,1,'A' UNION 
     SELECT 100,2,'B' UNION 
     SELECT 101,3,'A' UNION 
     SELECT 102,4,'A' UNION 
     SELECT 103,5,'B' UNION 
     SELECT 104,6,'B' UNION 
     SELECT 104,7,'A' UNION 
     SELECT 104,8,'A' 
    ) 
    SELECT * FROM (
     SELECT *,MAX(CASE WHEN type='A' THEN 1 ELSE 0 END)OVER(PARTITION BY tb.Member) HasA FROM tb 
    ) AS t WHERE (t.HasA=1 AND t.Type='A') OR t.HasA=0 
 
Member  ID   Type HasA 
----------- ----------- ---- ----------- 
100   1   A 1 
101   3   A 1 
102   4   A 1 
103   5   B 0 
104   7   A 1 
104   8   A 1 
+0

是的,這是有效的。但我不明白這將如何適用於有十幾種類別的案例。我怎樣才能把它變成更通用的解決方案? – JJ32

+0

你可以提供更多關於你的需求的細節嗎? –