프로그래밍SQL 분석가

복잡한 데이터 구조에서 여러 열에 대한 중복을 제거하고 고유한 레코드를 선택하려면 어떻게 해야 하며, DISTINCT, GROUP BY 및 ROW_NUMBER()의 작동 방식은 어떻게 다른가요?

Hintsage AI 어시스턴트로 면접 통과

답변.

SQL에서 고유한 레코드를 추출하는 것은 조직들이 다차원 데이터를 저장하기 시작하면서 매우 중요한 작업이 되었습니다. 때때로 여러 열의 조합에 대해 중복되지 않는 행을 출력해야 하고, 때때로 단일 키만 필요합니다.

문제의 역사:

초기 SQL 버전에서는 중복을 필터링하기 위해 DISTINCT만 제공되었습니다. 이후 GROUP BY와 같은 구조적 방법이 생겼고, UNIQUE한 값 집합에 대한 집계를 위한 것이며, 중복 레코트 처리에 대해 더 유연한 시나리오를 위한 ROW_NUMBER()와 같은 창 함수도 도입되었습니다. 예를 들어, '마지막' 또는 '첫 번째' 레코드를 선택할 수 있습니다.

문제:

DISTINCT는 SELECT에서 필드 집합 수준에서만 작동하지만 GROUP BY는 집계를 요구합니다. 창 함수는 고급 로직을 허용하지만 행 선택 순서를 충분히 고려하지 않으면 오류를 유발할 수 있습니다. 개발자들은 종종 이러한 접근 방식을 혼동하며, 이러한 오류는 잘못된 결과로 이어질 수 있습니다.

해결책:

  • 필요한 필드에 대해 고유한 행을 가져오려면 DISTINCT를 사용합니다.
  • 그룹화가 필요한 경우에는 GROUP BY를 사용합니다(예: 고유 쌍의 합계 또는 날짜).
  • ROW_NUMBER()와 같은 창 함수는 '중복 그룹에서 특정 기준에 따라 한 줄을 선택하는' 것과 같은 작업에 적합합니다.

코드 예제:

고객별로 가장 최근의 주문 레코드를 하나 선택하기:

WITH OrdersRank AS ( SELECT *, ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY OrderDate DESC) as rn FROM Orders ) SELECT * FROM OrdersRank WHERE rn = 1;

주요 특징:

  • DISTINCT는 SELECT에 명시된 필드만을 기준으로 고유한 행을 반환합니다.
  • GROUP BY는 집계가 필요한 경우 필수입니다.
  • ROW_NUMBER()는 원하는 우선순위/날짜/버전으로 행을 선택하는 데 최대한 유연합니다.

트릭 질문.

GROUP BY 없이 집계 함수와 함께 DISTINCT를 사용할 수 있습니까?

아니요, 집계 함수는 그룹화를 요구하며, 그렇지 않으면 구문 오류가 발생합니다.

SELECT COUNT(DISTINCT CustomerID) -- 올바름 SELECT SUM(Amount), DISTINCT CustomerID -- 오류!

GROUP BY에 SELECT의 모든 비집계 필드를 지정하지 않으면 어떻게 되나요?

이것은 대부분의 DBMS에서 오류를 발생시킵니다: SELECT의 모든 필드(집계 제외)는 GROUP BY에 나열되어야 합니다.

서브쿼리 없이 창 함수를 사용하여 중복을 '제거'할 수 있습니까?

아니요: 하나의 SELECT 내에서 ROW_NUMBER()를 사용한다고 해서 자동으로 '중복'을 필터링하지 않으며, 원하는 행을 선택하기 위한 외부 쿼리가 필요합니다.

일반적인 오류 및 반패턴

  • 많은 열과 행에서 DISTINCT를 사용하면 성능이 급격히 저하됩니다.
  • 필요한 집계 없이 GROUP BY를 사용하는 것은 무의미하며 자원을 낭비합니다.
  • 후속 필터 없이 창 함수를 사용하면 데이터는 중복으로 반환됩니다.

실제 사례

부정적인 사례

20백만 행의 테이블에 대해 모든 열에 대해 DISTINCT를 선택했습니다: 쿼리는 몇 시간 동안 실행되었고, 결과는 타임 아웃이나 데이터베이스 성능 저하였습니다.

장점:

  • 작성하기 간단합니다.

단점:

  • 대량 데이터에서 매우 비효율적입니다.

긍정적인 사례

창 함수를 사용하여: 고객에 대한 필요한 최신 레코드만 수 밀리초 내에 얻었습니다; 이전 및 반복할 필요가 없었습니다.

장점:

  • 매우 높은 성능.
  • 유연성.

단점:

  • 쿼리의 정교한 아키텍처와 창 함수에 대한 지식이 필요합니다.