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.