오늘 그런 질문을 받고 여러분이 참고하실 수 있도록 정리했습니다
다음과 같은 테이블이 있다고 가정해 보겠습니다.
Here Data 다음과 같은 특징이 있습니다. 하나의 DepartmentId에 여러 개의 이름이 있을 수 있으며 그 반대의 경우도 마찬가지입니다. 즉, Name과 DepartmentId는 다대다 관계를 갖습니다.
이제 DepartmentID에 따라 정렬한 후(첫 번째 단계) Name 열의 고유 값을 가져와(두 번째 단계) 유지하는 쿼리를 구현하고 싶습니다. 첫 번째 단계에서 한 단계 후의 상대적 순서입니다. 이 예에서 반환되어야 하는 세 가지 값은 다음과 같습니다. ACB
먼저 다음 작성 방법을 생각해 보겠습니다
Sample order by DepartmentId에서 고유한 이름 선택
의미적으로 보면 이는 자연스러운 일이다. 그러나 불행하게도 이 문은 전혀 실행될 수 없습니다.
이 오류의 의미는 DISTINCT(중복 값 제거)를 사용하면 다음과 같습니다. OrderBy 뒤에 나타납니다. 필드는 SELECT 뒤에도 나타나야 하지만 DepartmentID가 실제로 SELECT 뒤에 나타나면 분명히 중복된 값이 없으므로 결과는 확실히 잘못된 것입니다.
Sample order by DepartmentId에서 고유한 이름인 DepartmentId를 선택하세요
글쎄, DISINCT와 OrderBy를 조합하면 이런 문제가 발생하기 때문에, 예를 들어 다음과 같이 변경할 수 있습니다.
SELECT 고유 a.NameFROM(부서 ID별 샘플 주문에서 상위 100% 이름 선택) a
비교하고 싶습니다. 이전 작성 방식에서는 서브쿼리 기술을 사용했습니다. 또한 의미론적 관점에서 보면 still hot은 매우 직관적이고 명확합니다. 먼저 DepartmentId를 기준으로 정렬한 다음 중복 값을 찾고 싶습니다. 그런데 반환된 결과는 다음과 같습니다.
중복된 값이 실제로 제거되었음에도 불구하고 반환된 순서가 잘못되었습니다. 먼저 DepartmentId를 기준으로 정렬한 다음 중복된 값을 제거하고 정렬 후 상대 순서를 유지하기를 바랍니다.
왜 위와 같은 결과가 나오나요? 실제로 DISTINCT 자체가 정렬을 수행하기 때문에 이 동작은 변경할 수 없습니다(아래 실행 계획에서 확인할 수 있음). 그래서 사실, 우리가 이전에 했던 명령은 여기서 의미를 잃게 됩니다. [실제로 ADO.NET Entity Framework 등 ORM 도구에서 생성된 유사한 쿼리를 관찰하면 Order by 설정을 자동으로 폐기합니다.]
그러면 이렇게 됩니다. 이런 상황에서는 수요를 달성하는 것이 불가능할까요? 이 요구 사항은 드물지만 대부분의 경우 DISTINCT가 마지막 작업이므로 정렬을 수행하는 것이 합리적입니다.
생각해보니 DISTINCT의 행위가 내장되어 있는데 이 연산을 우회하는 것이 가능한 걸까요? 결국 제가 사용한 해결책은 다음과 같습니다. 각 이름에 번호를 할당할 수 있습니까? 예를 들어 A가 두 개인 경우 첫 번째 A에는 1, 두 번째 A에는 2 등으로 번호를 매깁니다. 그런 다음 쿼리할 때 먼저 정렬한 다음 1번으로 표시된 이름을 필터링하여 실제로 중복된 값이 제거되도록 했습니다.
SQL Server 2005에서는 ROW_NUMBER 함수를 제공하기 시작했습니다. 이 함수를 결합하여 다음 쿼리를 구현했습니다.
select a.Name from (select top 100 ratesName,DepartmentId,ROW_NUMBER( ) over( partition by name order by Departmentid) rowfrom 샘플 order by DepartmentId) awhere a.row=1order by a.DepartmentId
그러다가 아래와 같은 결과를 얻었습니다. 이 결과는 앞서 언급한 요구사항
을 충족해야 한다고 생각합니다. 이에 비해 이 쿼리의 효율성은 떨어질 것으로 예상됩니다(그림에서 몇 가지 단서를 볼 수 있습니다). 아래에). 그러나 요구 사항이 엄격한 경우 일부 성능을 희생하는 것은 놀라운 일이 아닙니다. 물론 더 나은 작성 방법이 있는지 알아보기 위해 더 연구할 수 있습니다. 그럼에도 불구하고 기본 제공 표준을 사용한 구현은 일반적으로 상대적으로 빠릅니다.