2011-09-19 5 views
2

에 대한 가장 최근의 레코드를 검색 :내가이 데이터를 각 고객

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

코드 (SQL 서버 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') 
내가 싶어

, 각 이름에 대한 ID가 가장 최근의 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; 

[DATE] 같은 예약어 (그리고 막연한 열 이름)를 피하려고 ...

+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은 다음과 같이 적용 사용할 수 있습니다 : 적절한 인덱스

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)을) 당신이 좋은 성능을 얻을 수 있습니다. 이 예제에서는 CROSS APPLY 하위 쿼리의 속도를 높이기 위해 테이블 ​​변수에 클러스터되지 않은 인덱스를 정의하기 위해 UNIQUE 제약 조건을 사용했습니다.