Postgres : 고유하지만 단 하나의 열


120

pgsql에 이름이있는 테이블이 있지만 (1 mio. 행 이상) 중복 항목도 많습니다. 내가 3 개 필드를 선택 : id, name, metadata.

나는 무작위로를 선택합니다 ORDER BY RANDOM()그리고 LIMIT 1000나는이 내 PHP 스크립트에 약간의 메모리를 절약하기 위해 여러 단계이다 할 수 있도록.

하지만 어떻게하면 이름이 중복되지 않는 목록 만 제공됩니다.

예를 들어 [1,"Michael Fox","2003-03-03,34,M,4545"]는 반환되지만 [2,"Michael Fox","1989-02-23,M,5633"]. 이름 필드는 가장 중요하며 선택을 할 때마다 목록에서 고유해야하며 무작위 여야합니다.

나는 GROUP BY name, bu로 시도한 다음 나에게 ID와 메타 데이터가 GROUP BY있거나 통합 기능에 있을 것으로 기대 하지만 어떻게 든 필터링하고 싶지 않습니다.

누구나 많은 열을 가져 오는 방법을 알고 있지만 하나의 열에서만 구별합니까?

답변:


226

하나 (또는 ​​n) 열에서만 구별을 수행하려면 다음을 수행하십시오.

select distinct on (name)
    name, col1, col2
from names

그러면 이름이 포함 된 모든 행이 반환됩니다. 반환 될 행을 제어하려면 다음을 주문해야합니다.

select distinct on (name)
    name, col1, col2
from names
order by name, col1

col1에 의해 주문되면 첫 번째 행을 반환합니다.

distinct on:

SELECT DISTINCT ON (expression [, ...])는 주어진 표현식이 동일하다고 평가되는 각 행 집합의 첫 번째 행만 유지합니다. DISTINCT ON 표현식은 ORDER BY와 동일한 규칙을 사용하여 해석됩니다 (위 참조). 원하는 행이 먼저 표시되도록 ORDER BY를 사용하지 않는 한 각 집합의 "첫 번째 행"은 예측할 수 없습니다.

DISTINCT ON 식은 가장 왼쪽의 ORDER BY 식과 일치해야합니다. ORDER BY 절에는 일반적으로 각 DISTINCT ON 그룹 내에서 원하는 행의 우선 순위를 결정하는 추가식이 포함됩니다.


주문을 잘 잡았습니다. 무작위 주문을 원한다고 언급했기 때문에 포함하지 않았지만 어쨌든 언급하는 것이 중요합니다.
Craig Ringer

order by name필수? 다른 결과를 얻을 수 order by col1있습니까?
Elliot Chance

1
@elliot yes name가 필요합니다. distinct on설명서를 확인하십시오 .
Clodoaldo Neto

1
나는 TSQL 팀이 이런 일을하는 합리적인 방법을 제공 할 수 있기를 바랍니다.
JTW 2015

적절한 postgresql 참조를
Ogaga Uzoh 2017

17

누구나 많은 열을 가져 오는 방법을 알고 있지만 하나의 열에서만 구별합니까?

당신 DISTINCT ON조항을 원합니다 .

샘플 데이터 나 전체 쿼리를 제공하지 않았으므로 보여 드릴 내용이 없습니다. 다음과 같이 작성하고 싶습니다.

SELECT DISTINCT ON (name) fields, id, name, metadata FROM the_table;

이는 예측할 수없는 ( "무작위"가 아닌) 행 집합을 반환합니다. 예측 가능하게 만들고 싶다면 ORDER BYClodaldo의 답변을 추가하십시오 . 진정으로 무작위로 만들고 싶다면 ORDER BY random().


이 DISTINCT ON 절을 사용하면 동일한 항목 이상으로 만 ORDER BY 할 수 있습니다. 따라서 DISTINCT ON (이름)이라고 말하면 이름으로 주문한 다음 원하는 다른 이름으로 주문해야합니다. 거의 이상적이지 않습니다.
Kevin Parker

Kevin, 외부 쿼리에서 CTE 또는 FROM의 하위 쿼리 및 ORDER BY를 사용할 수 있습니다.
Craig Ringer

예, 성능이 진행되는 것을 지켜보십시오 ... 인덱스 공간에서 가능한 전체 결과가 검색됩니다. 그것은 무엇을 전환 할 수 posgres가에 의해 다른 별개의 / 주문을 처리 할 수없는 이유만으로 900ms 하나에 적합한 인덱스와 10-20ms 쿼리합니다. 외부 쿼리 순서가 무엇이든 상관없이 내부 하위 쿼리의 인덱스를 사용하여 먼저 일치 항목을 찾은 다음 다시 정렬합니다. dba.stackexchange.com/questions/260852/
Kevin Parker

4
SELECT NAME,MAX(ID) as ID,MAX(METADATA) as METADATA 
from SOMETABLE
GROUP BY NAME

2
주의 그냥 단어 : ID 값 또는 메타 데이터 값을 반환하지 않을 수 있습니다 "함께"속한다
a_horse_with_no_name

@Novum 아니요. Michael의 최대 값을 요청했을 때 Michael의 행 중 하나에서 id 값을 가져오고 다른 행의 메타 데이터를 가져 오는 것을 의미합니다.
Clodoaldo Neto 2013 년

네, 실제 데이터 OP ​​사용에 크게 의존합니다. MIN 등을 사용해야 할 수도 있습니다. GROUP BY절에 없는 필드를 포함 할 수있는 방법을 방금 설명했습니다 .
David Jashi

다른 행의 다른 값이 섞이기 때문에 이것은 좋은 해결책이 아닙니다.
Elliot Chance
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.