2014-01-23 2 views
0

아래 표를 참조하십시오 ... changeno를 기반으로 한 최신 ID의 데이터 만 선택하려면 어떻게합니까? 나는이 결과를 원하는 것이주어진 행에서 ID의 최신 레코드 만 선택하십시오.

+----+--------------+------------+--------+ 
| id | data | changeno | | 
+----+--------------+------------+--------+ 
| 1 | Yes |  1 | | 
| 2 | Yes |  2 | | 
| 2 | Maybe |  3 | | 
| 3 | Yes |  4 | | 
| 3 | Yes |  5 | | 
| 3 | No |  6 | | 
| 4 | No |  7 | | 
| 5 | Maybe |  8 | | 
| 5 | Yes |  9 | | 
+----+---------+------------+-------------+ 

...

+----+--------------+------------+--------+ 
| id | data | changeno | | 
+----+--------------+------------+--------+ 
| 1 | Yes |  1 | | 
| 2 | Maybe |  3 | | 
| 3 | No |  6 | | 
| 4 | No |  7 | | 
| 5 | Yes |  9 | | 
+----+---------+------------+-------------+ 
나는 현재이 SQL 문이

...

SELECT ID, 데이터, MAX (changeno) 표 GROUP BY FROM changeno로 신분증;

분명히 내가 원하는 것을 반환하지 않습니다. 이것은 aggrerate 기능으로 인해 오류를 리턴해야합니다. GROUP BY 절 아래에 필드를 추가하면 작동하지만 원하는 결과를 반환하지 않습니다. SQL 문은 내가 생각할 수있는 가장 가까운 것입니다. 아무도 나를 도울 수 있다면 고맙겠습니다. 사전에 감사합니다 :)

답변

7

이 일반적으로 "greatest-n-per-group" 문제라고합니다. SQL 서버에서이 문제를 해결하는 한 가지 방법은 2005 년과 높은는 id 컬럼의 그룹화를 기반으로 계산 된 ROW_NUMBER()와 CTE를 사용하는 것입니다, 먼저 가장 큰하여 그 changeno 정렬 :

;WITH cte AS 
(
    SELECT id, data, changeno, 
    rn = ROW_NUMBER() OVER (PARTITION BY id ORDER BY changeno DESC) 
    FROM dbo.Table1 
) 
SELECT id, data, changeno 
    FROM cte 
    WHERE rn = 1 
    ORDER BY id; 
+0

안녕하세요. 실제로 작동합니다. 고마움 만 :) 그러나 당신은 그 ROW_NUMBER가 PARTITION 절과 함께 어떻게 작동하는지 조금 설명 할 수 있겠습니까? –

+0

PARTITION BY는 GROUP BY와 같습니다. id의 고유 한 값마다 해당 행을 모두보고 changeno가 정렬 한 행 번호를 큰 값에서 작은 값까지 적용합니다. 그래서 예를 들어 id 3을보고 4, 5, 6의 changeno 값을가집니다. 따라서 내림차순으로 순서를 지정하고 1에서 6, 2에서 5, 3에서 4를 적용합니다. 각 이드에 대해이 작업을 수행합니다. 외부 쿼리는 적용된 행 번호가 1 인 행만 가져옵니다. 추가 정보 [여기] (http://technet.microsoft.com/en-us/library/ms186734.aspx) 및 [여기] (http : //technet.microsoft.com.com/ko-ko/library/ms189461.aspx). –

+2

이것은 이상한 일이지만, 나는 당신이 말한 것을 바탕으로 모든 것을 실제로 이해했습니다. 나는 내가 afterall이라고 생각하는만큼 바보가 아니다 :) @Aaron Bertrand. 감사합니다 억 시간이 시간 : –

4

당신은 이것에 대한 row_number()를 사용하려면 :

select id, data, changeno 
from (SELECT t.*, 
      row_number() over (partition by id order by changeno desc) as seqnum 
     FROM Table1 t 
    ) t 
where seqnum = 1; 
+0

, 그리고 더 짧은 :) 고마워. –

+0

죄송합니다. 유감스럽게도 답변 2 개를 표시 할 수 있다고 생각합니다. 귀하의 것을 선택하겠습니다. @AaronBertrand –

+0

@AaronBertrand. . . 당신은 여기에 타임 스탬프를 읽는 법을 가르쳐 준 분이 십니다. 내 대답은 7 초 전이었다. –

0

아니 잘 형성되거나 성능 최적화 된 쿼리를 사용하지만 작은 작업의 경우 제대로 작동합니다.

SELECT * TEST FROM WHERE IN changeno 다른 대안에 대한

+1

당신이 개요 문제 이외에, 이것은 우리가 'changeno'가 고유하다는 것을 알고있는 경우에만 작동합니다. 샘플 데이터를 기반으로, 이것은 합리적인 가정이지만, 우리는 알지 못하기 때문에 (이후의 독자들이 모를 수도 있기 때문에) ... –

+0

changeno가 주어진 id에 대해 고유하지 않으면 가져 왔습니다. @AaronBertrand 당신의 솔루션은 훌륭합니다. 고맙습니다. 파티션에 대해 알아보십시오. :) – DhanushD

0

(MAX (changeno) ID로 TEST FROM 그룹을 선택) :이 위 정확히 하나처럼 작동

DECLARE @Table1 TABLE 
(
id INT, data VARCHAR(5), changeno INT 
); 

INSERT INTO @Table1 
SELECT 1,'Yes',1 
UNION ALL 
SELECT 2,'Yes',2 
UNION ALL 
SELECT 2,'Maybe',3 
UNION ALL 
SELECT 3,'Yes',4 
UNION ALL 
SELECT 3,'Yes',5 
UNION ALL 
SELECT 3,'No',6 
UNION ALL 
SELECT 4,'No',7 
UNION ALL 
SELECT 5,'Maybe',8 
UNION ALL 
SELECT 5,'Yes',9 

SELECT Y.id, Y.data, Y.changeno 
FROM @Table1 Y 
INNER JOIN (
    SELECT id, changeno = MAX(changeno) 
    FROM @Table1 
    GROUP BY id 
) X ON X.id = Y.id 
WHERE X.changeno = Y.changeno 
ORDER BY Y.id 
관련 문제