지정된 열의 값이 중복된 레코드 단위에서 첫 번째 항목만 추출합니다
일반적으로 중복 레코드를 하나만 추출 할 때 가장 먼저 떠오르 distinct
는 것은 다음과 같습니다.
distinct
중복 열과 동시에 검색하려는 다른 열을 지정할 수 없습니다.
또한distinct
추출에 중복되지 않은 레코드가 포함되므로 이 요구 사항과 일치하지 않습니다.
제목만으로는 무엇을 하고 싶은지 알 수 없다고 생각하기 때문에, 샘플 레코드를 예로 들어 보겠습니다. 내가하고 싶은 것은 다음과 같은 추출 결과입니다.
ID | 이름 |
---|---|
1 | 이름 1 |
2 | 이름 2 |
3 | 이름 3 |
3 | 이름 3@example.com |
4 | 이름 4 이름 4@example.com |
4 | 이름 4@example.com |
4 | 이름 4@example.com |
다음과 같이 가져옵니다.
ID | 이름 |
---|---|
3 | 이름 3@example.com |
4 | 이름 4@example.com |
ID 1과 2는 중복되지 않으므로 포함되지 않습니다. ID 3과 4는 중복되므로 그 중 하나가 검색됩니다. 그러나 이번에는 DB 스토리지 순서에서 첫 번째 레코드를 가져오지 않습니다. 또한 "이름에 @ 표시가 포함되어 있음"및 "이름에 적은 수의 문자가 있음"이라는 조건에서 우선 순위에 따라 이름의 첫 번째 줄을 원한다고 가정합니다.
위의 조건은 다음 SQL을 사용하여 얻을 수 있습니다. 그러나 하위 쿼리를 사용하고 있으며 성능을 확인하지 않았습니다.
select
*
from
(select *, row_number() over(order by ID asc) as RowNum from SampleTable) tableMain
where tableMain.RowNum =
(
select
top(1) RowNum
from
(select *, row_number() over(order by ID asc) as RowNum from SampleTable) tableSub
where
tableMain.ID = tableSub.ID
and exists (
select
*
from
SampleTable
where
tableSub.ID = ID
having
count(*) >= 2
)
order by
case when charindex(N'@', Name) >= 1 then 0 else 1 end, len(Name)
)
중복 행은 및 count
로 확인됩니다having
. group by
외부에서 확인해야 할 키 열, 여기서 ID
열은 로 좁혀집니다where
.
첫 번째 행을 order by
검색하기 위한 우선 순위는 에 의해 지정됩니다. charindex
len
여기에서 지정된 문자와 문자열의 길이가 포함되어 있는지 확인합니다.
top
에서 각 중복 레코드의 첫 번째 행을 가져오기만 하면 됩니다.
원래는 괜찮지만 "ID: 4, Name: Name 4@example.com"와 같이 정확히 같은 값을 가진 레코드가 두 개 이상 있는 경우 필연적으로 두 개의 레코드를 얻게 됩니다.
row_number
따라서 를 사용하여 각 행에 대해 식별할 수 있도록 추가되므로 정확히 동일한 값을 가진 하나의 레코드만 검색할 수 있습니다.
정확히 동일한 레코드가 존재하지 row_number
않는 것으로 알려진 경우 를 추가하지 않고 기존 레코드의 값을 확인하는 것이 더 낫다고 생각합니다.
중복 여부를 확인해야 할 키가 여러 개 있는 경우 각각에 대한 키 열 수를 늘릴 수 있습니다. 예를 들어 다음 레코드를 고려합니다. 중복 여부를 확인할 열은 "ID1"과 "ID2"입니다.
ID1 | ID2 | 이름 |
---|---|---|
1 | 1 | 이름 1 |
2 | 1 | 이름 2 |
3 | 1 | 이름 31 |
3 | 2 | 이름 32 |
4 | 1 | 이름41 |
4 | 2 | 이름42 |
4 | 2 | 이름 4@example.com |
5 | 1 | 이름 555@example.com |
5 | 1 | 이름 55@example.com |
5 | 2 | 이름 5@example.com |
6 | 1 | 이름 6 |
6 | 1 | 이름 66@example.com |
6 | 2 | 이름 6 |
6 | 2 | 이름 6 |
취득 결과는 다음과 같습니다.
ID1 | ID2 | 이름 |
---|---|---|
4 | 2 | 이름 4@example.com |
5 | 1 | 이름 55@example.com |
6 | 1 | 이름 66@example.com |
6 | 2 | 이름 6 |
SQL은 다음과 같습니다. 키 열이 지정된 부분을 간단히 늘릴 수 있습니다.
select
*
from
(select *, row_number() over(order by ID1 asc, ID2 asc) as RowNum from SampleTable) tableMain
where tableMain.RowNum =
(
select
top(1) RowNum
from
(select *, row_number() over(order by ID1 asc, ID2 asc) as RowNum from SampleTable) tableSub
where
tableMain.ID1 = tableSub.ID1
and tableMain.ID2 = tableSub.ID2
and exists (
select
*
from
SampleTable
where
tableSub.ID1 = ID1
and tableSub.ID2 = ID2
having
count(*) >= 2
)
order by
case when charindex(N'@', Name) >= 1 then 0 else 1 end, len(Name)
)