답변:
SELECT DISTINCT a,b,c FROM t
이다 대략 동일합니다 :
SELECT a,b,c FROM t GROUP BY a,b,c
더 강력하기 때문에 GROUP BY 구문에 익숙해지는 것이 좋습니다.
귀하의 쿼리에 대해 다음과 같이하십시오.
UPDATE sales
SET status='ACTIVE'
WHERE id IN
(
SELECT id
FROM sales S
INNER JOIN
(
SELECT saleprice, saledate
FROM sales
GROUP BY saleprice, saledate
HAVING COUNT(*) = 1
) T
ON S.saleprice=T.saleprice AND s.saledate=T.saledate
)
지금까지 답변을 정리하고 정리하고 개선하면 다음과 같은 우수한 쿼리에 도달하게됩니다.
UPDATE sales
SET status = 'ACTIVE'
WHERE (saleprice, saledate) IN (
SELECT saleprice, saledate
FROM sales
GROUP BY saleprice, saledate
HAVING count(*) = 1
);
어느 쪽 보다 훨씬 빠릅니다. PostgreSQL 8.4 및 9.1에 대한 테스트에서 요소 10-15에 의해 현재 허용되는 답변의 성능을 깎습니다.
그러나 이것은 여전히 최적과는 거리가 멀다. NOT EXISTS
더 나은 성능을 위해서는 (반) 반 접합을 사용하십시오 . EXISTS
표준 SQL이며 (이 질문이 나오기 오래 전부터 PostgreSQL 7.2 이후로) 영원히 존재했으며 제시된 요구 사항을 완벽하게 충족시킵니다.
UPDATE sales s
SET status = 'ACTIVE'
WHERE NOT EXISTS (
SELECT FROM sales s1 -- SELECT list can be empty for EXISTS
WHERE s.saleprice = s1.saleprice
AND s.saledate = s1.saledate
AND s.id <> s1.id -- except for row itself
)
AND s.status IS DISTINCT FROM 'ACTIVE'; -- avoid empty updates. see below
db <> fiddle here
이전 SQL 바이올린
테이블에 대한 기본 또는 고유 키가없는 경우 ( id
예제에서) ctid
이 쿼리의 목적으로 시스템 열 을 대체 할 수 있습니다 (다른 목적으로는 사용하지 않음).
AND s1.ctid <> s.ctid
모든 테이블에는 기본 키가 있어야합니다. 아직없는 경우 추가하십시오. Postgres 10+에서 a serial
또는 IDENTITY
열을 제안합니다 .
관련 :
EXISTS
안티-세미-조인 의 하위 쿼리 는 첫 번째 속줄이 발견되는 즉시 평가를 중지 할 수 있습니다 (더 이상 볼 필요가 없습니다). 중복이 거의없는 기본 테이블의 경우 약간 더 효율적입니다. 중복이 많은이 될 방법이 더 효율적입니다.
이미이 status = 'ACTIVE'
업데이트가 있는 행의 경우 아무 것도 변경하지 않지만 여전히 전체 비용으로 새 행 버전을 삽입합니다 (사소한 예외 적용). 일반적으로 이것을 원하지 않습니다. WHERE
이것을 피하고 더 빠르게 만들기 위해 위에서 설명한 것과 같은 다른 조건을 추가하십시오 .
경우 status
정의됩니다 NOT NULL
, 당신은 할 수 단순화 할 수 있습니다 :
AND status <> 'ACTIVE';
열의 데이터 유형은 <>
연산자 를 지원해야합니다 . json
그렇지 않은 유형도 있습니다 . 보다:
이 쿼리는 Joel 이 현재 허용하는 답변 과 달리 NULL 값을 동일하게 취급하지 않습니다. 다음 두 행은 (saleprice, saledate)
"고유 한"것으로 간주됩니다 (사람의 눈과 동일하게 보이지만).
(123, NULL)
(123, NULL)
NULL 값은 SQL 표준에 따라 동일하게 비교되지 않기 때문에 고유 인덱스 및 거의 다른 곳에서도 전달됩니다. 보다:
OTOH, GROUP BY
, DISTINCT
또는 DISTINCT ON ()
동일 등을 취급 NULL 값. 달성하려는 대상에 따라 적절한 쿼리 스타일을 사용하십시오. NULL 비교를 동일하게 만들기 위해 일부 또는 모든 비교 IS NOT DISTINCT FROM
대신 이 빠른 쿼리를 계속 사용할 수 있습니다 =
. 더:
비교중인 모든 열이 정의 NOT NULL
되어 있으면 동의 할 여지가 없습니다.
count(*)
이다 더 이상 효율적 count(<expression>)
. 먹어봐. Postgres는이 집계 함수 변형을 더 빠르게 구현합니다. 어쩌면 Postgres를 다른 RDBMS와 혼동하고 있습니까?
쿼리의 문제점은 GROUP BY 절을 사용할 때 (기본적으로 distinct를 사용하여 수행함) 함수별로 그룹화하거나 집계하는 열만 사용할 수 있다는 것입니다. 다른 값이있을 수 있으므로 열 ID를 사용할 수 없습니다. 귀하의 경우에는 HAVING 절로 인해 항상 하나의 값만 있지만 대부분의 RDBMS는이를 인식하기에 충분하지 않습니다.
그러나 이것은 작동해야하며 조인이 필요하지 않습니다.
UPDATE sales
SET status='ACTIVE'
WHERE id IN (
SELECT MIN(id) FROM sales
GROUP BY saleprice, saledate
HAVING COUNT(id) = 1
)
MIN 대신 MAX 또는 AVG를 사용할 수도 있습니다. 일치하는 행이 하나만있는 경우 열 값을 반환하는 함수 만 사용해야합니다.
하나의 열 'GrondOfLucht'에서 고유 값을 선택하고 싶지만 'sortering'열에 주어진 순서대로 정렬해야합니다. 하나의 열에 대한 고유 값을 사용할 수 없습니다.
Select distinct GrondOfLucht,sortering
from CorWijzeVanAanleg
order by sortering
또한 '정렬'열을 제공하고 'GrondOfLucht'AND '정렬'이 고유하지 않으므로 결과는 모든 행이됩니다.
GROUP을 사용하여 'GrondOfLucht'의 레코드를 'sortering'에 의해 주어진 순서대로 선택하십시오.
SELECT GrondOfLucht
FROM dbo.CorWijzeVanAanleg
GROUP BY GrondOfLucht, sortering
ORDER BY MIN(sortering)
DBMS가 다음과 같이 여러 열로 구별을 지원하지 않는 경우 :
select distinct(col1, col2) from table
일반적으로 다중 선택은 다음과 같이 안전하게 실행할 수 있습니다.
select distinct * from (select col1, col2 from table ) as x
이것은 대부분의 DBMS에서 작동 할 수 있으며 그룹화 기능을 피하기 때문에 솔루션별로 그룹화하는 것보다 빠를 것으로 예상됩니다.