З одиниці запису витягти тільки перший, де дублюється значення вказаного стовпця
Зазвичай, коли ви витягуєте лише один дублікат запису, перше, що спадає на думку, це distinct
те,
distinct
Не дозволяє вказати дублікат стовпця та інший стовпець, який потрібно отримати одночасно.
Крім того, не відповідає цій вимозі,distinct
оскільки включає у витяг записи, що не дублюються.
Я не думаю, що ви можете зрозуміти, що ви хочете зробити за допомогою одного лише заголовку, тому давайте візьмемо для прикладу зразок запису. Що я хочу зробити, так це отримати наступний результат екстракції.
Ім'я | ідентифікатора |
---|---|
1 | Ім'я 1 |
2 | Ім'я 2 |
3 | Ім'я 3 |
3 | Назвіть 3@example.com |
4 | Ім'я 4 Ім'я 4@example.com |
4 | Назвіть 4@example.com |
4 | Назвіть 4@example.com |
Отримують його наступним чином:
Ім'я | ідентифікатора |
---|---|
3 | Назвіть 3@example.com |
4 | Назвіть 4@example.com |
Ідентифікатори 1 та 2 не включені, оскільки вони не є дублікатами. ID 3 і 4 є дублікатами, тому один з них витягується. Однак цього разу ми не отримаємо перший запис у порядку зберігання БД. Крім того, припустимо, що ви хочете, щоб перший рядок імені був в порядку пріоритету за умови, що «Ім'я містить позначку @» і «Ім'я має невелику кількість символів».
Вищезазначена умова може бути отримана за допомогою наступного 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)
)
Повторювані рядки перевіряються having
за допомогою і count
. 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)
)