열의 각 고유 값에 대해 첫 번째 행만 선택하는 방법


96

고객 주소 테이블이 있다고 가정 해 보겠습니다.

CName           |   AddressLine
-------------------------------
John Smith      | 123 Nowheresville
Jane Doe        | 456 Evergreen Terrace
John Smith      | 999 Somewhereelse
Joe Bloggs      | 1 Second Ave

표에서 John Smith와 같은 한 고객은 여러 주소를 가질 수 있습니다. 'CName'에 중복 항목이있는 첫 번째 행만 반환하려면이 테이블에 대한 선택 쿼리가 필요합니다. 이 테이블의 경우 세 번째를 제외한 모든 행을 반환해야합니다 (또는 첫 번째-두 주소 중 하나라도 괜찮지 만 하나만 반환 될 수 있음). 서버가 이전에 열 값을 본 적이 있는지 여부를 기준으로 필터링하기 위해 SELECT 쿼리에 추가 할 수있는 키워드가 있습니까?

답변:


125

어떤 주소가 사용되는지 신경 쓰지 않는다고 말하는 경우 매우 간단한 대답입니다.

SELECT
    CName, MIN(AddressLine)
FROM
    MyTable
GROUP BY
    CName

예를 들어 "삽입 된"열에 따라 첫 번째를 원하는 경우 다른 쿼리입니다.

SELECT
    M.CName, M.AddressLine,
FROM
    (
    SELECT
        CName, MIN(Inserted) AS First
    FROM
        MyTable
    GROUP BY
        CName
    ) foo
    JOIN
    MyTable M ON foo.CName = M.CName AND foo.First = M.Inserted

열 10 개를 선택할 때 이러한 방식으로 사용되지는 않을 수도 있습니다. 또한 비트 유형의 열을 허용하지 않는 것 같습니다.
nuit9 2011 년

1
@ nuit9 : 물론 비트와 열 10 개에서는 작동하지 않습니다. 이 사실 중 어느 것도 귀하의 질문에 해당되지 않습니다. 두 번째 기술 또는 Ben Thul의 기술을 사용합니다. 더 일반적으로 해결하는 방법에 대한 포인터와 함께 구체적으로 요청한 내용에 대답했습니다.
gbn

첫 번째 부분은 비트 유형 열이 아닌 여러 열에서 작동합니다. 그래도 MS SQL 서버 2016에서 이것을 테스트했습니다.
netfed

24

SQL 2k5 +에서는 다음과 같이 할 수 있습니다.

;with cte as (
  select CName, AddressLine,
  rank() over (partition by CName order by AddressLine) as [r]
  from MyTable
)
select CName, AddressLine
from cte
where [r] = 1

5
순위, 파티션을 무엇을 설명해주십시오 [R] 할
로베르토

10

row_number()행의 행 번호를 가져 오는 데 사용할 수 있습니다 . over명령을 사용합니다. 이 partition by절은 번호 매기기를 다시 시작할시기를 지정 order by하고 행 번호를 정렬 할 항목을 선택합니다. order by쿼리 끝에 를 추가하더라도 over번호를 매길 때 명령 의 순서가 유지 됩니다.

select *
from mytable
where row_number() over(partition by Name order by AddressLine) = 1

6
postgresql에서는 WHERE 절에서 창 함수를 사용할 수 없습니다
ekanna

3
MS-SQL에는 허용되지 않습니다.
Mixxiphoid

1
ROW_NUMBER()WhereTeradata의 절에서도 작동하지 않습니다
Pirate X

6

다음 row_numer() over(partition by ...)과 같은 구문을 사용할 수 있습니다 .

select * from
(
select *
, ROW_NUMBER() OVER(PARTITION BY CName ORDER BY AddressLine) AS row
from myTable
) as a
where row = 1

이것이 row하는 일은 동일한 것을 볼 때마다 증가하는 카운터 인 라는 열을 생성하고 CName해당 항목을 기준으로 인덱싱한다는 것 AddressLine입니다. 부과함으로써 where row = 1, 하나는 선택할 수있는 CName그의 AddressLine첫번째 알파벳 순으로 온다. (가) 경우 order by했다 desc, 다음은 선택 것이다 CName그의 AddressLine마지막 순으로 온다.


1

이렇게하면 각 중복 행의 행이 하나씩 제공됩니다. 또한 비트 유형 열을 제공하며 적어도 MS Sql Server에서 작동합니다.

(select cname, address 
from (
  select cname,address, rn=row_number() over (partition by cname order by cname) 
  from customeraddresses  
) x 
where rn = 1) order by cname

대신 모든 중복을 찾으려면 rn = 1을 rn> 1로 변경하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.