sourcecode

여러 열에서 DISTINCT를 선택하려면 어떻게 해야 합니까?

codebag 2023. 5. 8. 22:13
반응형

여러 열에서 DISTINCT를 선택하려면 어떻게 해야 합니까?

나는 두 개의 열을 합친 것이 모두 다른 테이블에서 모든 행을 검색해야 합니다.그래서 나는 같은 날에 발생한 다른 판매가 없는 모든 판매를 같은 가격으로 원합니다.날짜와 가격을 기준으로 고유한 판매가 활성 상태로 업데이트됩니다.

그래서 내 생각은:

UPDATE sales
SET status = 'ACTIVE'
WHERE id IN (SELECT DISTINCT (saleprice, saledate), id, count(id)
             FROM sales
             HAVING count = 1)

하지만 그보다 더 멀리 가면 제 뇌가 아파요.

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 
    );

둘 중 어느 쪽보다 훨씬 빠른 속도입니다.(Postgre에 대한 내 테스트에서) 요인 10 - 15에 의해 현재 승인된 답변의 성능을핵화합니다.SQL 8.4 및 9.1).

그러나 이것은 여전히 최적의 상태와는 거리가 멉니다.더 나은 성능을 위해 (안티) 세미 조인을 사용합니다. EXISTS표준 이 SQL 이후).SQL 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<>여기로 이동
올드 sqlifiddle

행을 식별하는 고유 키

키가(테이블에대기키또고없키경가는우유는본한▁for경▁if우없)id 열을 시스템 열로 할 수 .ctid이 쿼리의 목적(다른 목적은 아님):

   AND    s1.ctid <> s.ctid

모든 테이블에는 기본 키가 있어야 합니다.아직 없으면 하나 더 추가합니다.나는 제안합니다.serial 는또.IDENTITYPostgres 10+의열다니입.

관련:

이게 어떻게 더 빨라요?

의 하위 EXISTS안티스파이웨어는 첫 번째 속임수가 발견되는 즉시 평가를 중지할 수 있습니다(자세히 살펴봐야 할 의미가 없음).중복 항목이 거의 없는 기본 테이블의 경우 이 방법이 약간 더 효율적일 뿐입니다.중복 데이터가 많으면 효율성이 훨씬 높아집니다.

빈 업데이트 제외

이있는행경이 status = 'ACTIVE'이 업데이트는 아무것도 변경하지 않지만 새 행 버전을 전체 비용으로 삽입합니다(예외 사항이 적용됨).일반적으로, 당신은 이것을 원하지 않습니다. 다항목추를 합니다.WHERE위에서 설명한 것과 같은 조건을 사용하여 이를 방지하고 속도를 더욱 높일 수 있습니다.

한다면status는 정의됩니다.NOT NULL다음과 같이 단순화할 수 있습니다.

AND status <> 'ACTIVE';

은 열데이다지합원니다야해를 해야 합니다.<>교환입니다.다음과 같은 유형json하지 마. 참조:

NULL 처리에서 미묘한 차이가 있음

이 쿼리는 (조엘이 현재 수락한 답변과 달리) NULL 값을 동일하게 처리하지 않습니다.다음 두 행:(saleprice, saledate)(사람의 눈과 동일하게 보이지만) "눈"의 자격이 있습니다.

(123, NULL)
(123, NULL)

또한 NULL 값이 SQL 표준에 따라 동일하게 비교되지 않기 때문에 고유 인덱스와 거의 모든 위치에 전달됩니다.참조:

OTOH,GROUP BY,DISTINCT또는DISTINCT ON ()NULL 값을 동일하게 처리합니다.원하는 항목에 따라 적절한 쿼리 스타일을 사용합니다.이 더 빠른 쿼리를 다음과 같이 사용할 수 있습니다.=NULL 비교를 동일하게 하기 위해 일부 또는 모든 비교를 수행합니다. 정보

열이 NOT NULL이견의 여지가 없습니다.

쿼리의 문제는 GROUP BY 절을 사용할 때(기본적으로 별개의 기능을 사용하여 수행함) 그룹화하거나 함수를 집계하는 열만 사용할 수 있다는 것입니다.다른 값이 있을 수 있으므로 열 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를 사용할 수도 있습니다. 일치하는 행이 하나만 있는 경우 열 값을 반환하는 함수만 사용하는 것이 중요합니다.

DBMS가 다음과 같은 여러 열로 구분할 수 없는 경우:

select distinct(col1, col2) from table

일반적으로 다중 선택은 다음과 같이 안전하게 실행할 수 있습니다.

select distinct * from (select col1, col2 from table ) as x

이것은 대부분의 DBMS에서 작동할 수 있기 때문에 그룹화 기능을 사용하지 않기 때문에 솔루션별 그룹화보다 빠를 것으로 예상됩니다.

하나의 열 'GrandOfLucht'에서 고유한 값을 선택하고 싶지만 'sorting' 열에 지정된 순서대로 정렬되어야 합니다.다음을 사용하여 한 열의 고유한 값을 가져올 수 없습니다.

Select distinct GrondOfLucht,sortering
from CorWijzeVanAanleg
order by sortering

또한 'Sortering' 열에 'GrandOfLucht' 및 'Sortering'이 고유하지 않기 때문에 결과는 모든 행이 됩니다.

GROUP을 사용하여 'GrandOfLucht'의 레코드를 정렬 순서대로 선택합니다.

SELECT        GrondOfLucht
FROM            dbo.CorWijzeVanAanleg
GROUP BY GrondOfLucht, sortering
ORDER BY MIN(sortering)

언급URL : https://stackoverflow.com/questions/54418/how-do-i-or-can-i-select-distinct-on-multiple-columns

반응형