2011-09-19 90 views
2

我有這樣的數據:檢索最新記錄每個客戶

ID NAME DATE 
3 JOHN 2011-08-08 
2 YOKO 2010-07-07 
1 JOHN 2009-06-06 

碼(用於SQL Server 2005):

DECLARE @TESTABLE TABLE (id int, name char(4), date smalldatetime) 
INSERT INTO @TESTABLE VALUES (3, 'JOHN', '2011-08-08') 
INSERT INTO @TESTABLE VALUES (2, 'YOKO', '2010-07-07') 
INSERT INTO @TESTABLE VALUES (1, 'JOHN', '2009-06-06') 

我想,每一個名稱,編號有最近的DATE。像這樣:

3 JOHN 2011-08-08 
2 YOKO 2010-07-07 

完成此操作的最優雅方式是什麼?

回答

12
;WITH x AS 
(
    SELECT ID, NAME, [DATE], 
     rn = ROW_NUMBER() OVER 
     (PARTITION BY NAME ORDER BY [DATE] DESC) 
    FROM @TESTABLE 
) 
SELECT ID, NAME, [DATE] FROM x WHERE rn = 1 
    ORDER BY [DATE] DESC; 

儘量避免保留字(和模糊的列名)像 ...

+2

+1對於保留字謹慎 – JNK

+0

這是優雅的。它比JOIN 2版本更高效(更快)嗎? –

+2

@idevlop - 我認爲速度將取決於您的索引而不是查詢。我認爲這與其他版本之間的差異應該是最小的性能。 – JNK

4
SELECT <fields> 
FROM SourceTable st 
INNER JOIN (SELECT name, MAX(Datefield) as Datefield 
      FROM SourceTable 
      GROUP BY name) x 
    ON x.Name = st.name 
    AND x.datefield = st.datefield 
1

如果源表是標準化(例如:一個表,爲客戶和另一個表訂單),可以使用CROSS APPLY這樣的:

DECLARE @CUSTOMER TABLE(id int primary key, name char(4)); 
INSERT INTO @CUSTOMER VALUES (3, 'JOHN'); 
INSERT INTO @CUSTOMER VALUES (2, 'YOKO'); 
INSERT INTO @CUSTOMER VALUES (1, 'JOHN'); 


DECLARE @ORDER TABLE (orderid int identity(1,1) primary key, customerid int, [date] smalldatetime, UNIQUE(customerid,[date] DESC,orderid)) ; 
INSERT INTO @ORDER VALUES (3, '2011-08-08'); 
INSERT INTO @ORDER VALUES (2, '2010-07-07'); 
INSERT INTO @ORDER VALUES (1, '2009-06-06'); 

SELECT * 
FROM @CUSTOMER c 
CROSS APPLY 
(
    SELECT TOP 1 o.* 
    FROM @ORDER o 
    WHERE o.customerid = c.id 
    ORDER BY o.[date], o.orderid DESC 
) ca 

有了正確的索引(UNIQUE(customerid,[date] DESC,orderid)),你可以得到一個不錯的表現。 在這個例子中,我使用了一個UNIQUE約束來定義一個表變量的非聚集索引來加速CROSS APPLY子查詢。