2015-10-07 48 views
1

我有一個SQL表,其數據如下。爲具有相關子值的鍵選擇最近的條目

key entry_no type_1 type_2 text 
1 1   A  Y  text 1 
1 2   B  Y  text 2 
1 3   B  Y  text 3 
1 4   A  Y  text 4 
1 5   B    text 5  
1 6   C  Y  text 6 

我需要做的是對指定的鍵(例如,1)提取物具有用於每個組TYPE_1最高entry_no其中TYPE_2等於「Y」的行(例如A,B或C)。

E.g.從上面我想返回以下內容:

key entry_no type_1 type_2 text 
1 3   B  Y  text 3 
1 4   A  Y  text 4 
1 6   C  Y  text 6 

我已經嘗試了幾種不同的方法可以做到這一點,但不能得到它的權利(我不是SQL專家,雖然)。這可能嗎?

我想我需要做一些類型的子查詢?

+0

請編輯的問題,並添加一個標籤與您所使用的數據庫管理系統(Postgres的時,SQL Server,Oracle等)及其版本。除非你需要ANSI標準SQL的解決方案。 –

+0

標籤根據要求更新。 – jj2

回答

1

通常這種類型的查詢被稱爲top-N-per-group。在SQL Server中至少有兩種獲取結果的方法。一個使用ROW_NUMBER,另一個使用CROSS APPLY。如果每組有很多組和很少的行,那麼使用ROW_NUMBER會更有效。如果您的組數很少,但每個組都有很多行,並且您有適當的索引,則使用CROSS APPLY會更有效。

https://dba.stackexchange.com/questions/86415/retrieving-n-rows-per-group

http://sqlmag.com/sql-server/seek-and-you-shall-scan-part-i-when-optimizer-doesnt-optimize

樣本數據

DECLARE @T TABLE 
    ([key] int, 
    [entry_no] int, 
    [type_1] varchar(1), 
    [type_2] varchar(1), 
    [text] varchar(50)); 

INSERT INTO @T 
    ([key], [entry_no], [type_1], [type_2], [text]) 
VALUES 
    (1, 1, 'A', 'Y', 'text 1'), 
    (1, 2, 'B', 'Y', 'text 2'), 
    (1, 3, 'B', 'Y', 'text 3'), 
    (1, 4, 'A', 'Y', 'text 4'), 
    (1, 5, 'B', '', 'text 5'), 
    (1, 6, 'C', 'Y', 'text 6'); 

變體與ROW_NUMBER

DECLARE @VarKey int = 1; 

WITH 
CTE 
AS 
(
    SELECT 
     [key] 
     ,[entry_no] 
     ,[type_1] 
     ,[type_2] 
     ,[text] 
     ,ROW_NUMBER() 
      OVER (PARTITION BY [type_1] ORDER BY [entry_no] DESC) AS rn 
    FROM @T 
    WHERE 
     [key] = @VarKey 
     AND [type_2] = 'Y' 
) 
SELECT 
    [key] 
    ,[entry_no] 
    ,[type_1] 
    ,[type_2] 
    ,[text] 
FROM CTE 
WHERE rn = 1 
ORDER BY [type_1]; 

結果

| key | entry_no | type_1 | type_2 | text | 
|-----|----------|--------|--------|--------| 
| 1 | 4  | A  | Y  | text 4 | 
| 1 | 3  | B  | Y  | text 3 | 
| 1 | 6  | C  | Y  | text 6 | 
1
select max(entry_no) 
from table 
group by type_1 
where key = 1 and type_2 = 'Y' 
+0

這是一個不錯的簡單解決方案(儘管它確實讓我想哭一點)。我怎樣才能返回「文本」字段和「type_1」字段? – jj2

+0

我想不是在一個語句中,因爲您必須按文本和type_1進行分組,並且這些值對於單個entry_no是不相等的。 – Smutje

0
with cte as (
    select 1 as [key] , 1 as entry_no  , 'A' as type_1  ,'Y' as type_2  ,'text 1' as [text] 
    union select 1 , 2  , 'B'  ,'Y'  ,'text 2' 
    union select 1 , 3  , 'B'  ,'Y'  ,'text 3' 
    union select 1 , 4  , 'A'  ,'Y'  ,'text 4' 
    union select 1 , 5  , 'B'  ,' '  ,'text 5'  
    union select 1 , 6  , 'C'  ,'Y'  ,'text 6' 
    ) 
    select *From cte 
    where entry_no = (select max(entry_no) from cte t where cte.[key] = t.[key] and cte.type_1 = t.type_1 and t.type_2='Y')