Виберіть оператор, щоб знайти дублікати в певних полях


415

Чи можете ви допомогти мені з операторами SQL знайти дублікати у кількох полях?

Наприклад, у псевдокоді:

select count(field1,field2,field3) 
from table 
where the combination of field1, field2, field3 occurs multiple times

і з вищезазначеного твердження, якщо є кілька випадків, я хотів би вибрати кожен запис, крім першого .


3
ваш псевдо-код неоднозначний, плюс ви не визначаєте порядок, згідно з яким ви не хочете першого. Я пропоную вам дати деякі зразкові дані.
Нерозумно

Відповіді:


840

Щоб отримати список полів, для яких є кілька записів, ви можете використовувати ..

select field1,field2,field3, count(*)
  from table_name
  group by field1,field2,field3
  having count(*) > 1

Перегляньте це посилання для отримання додаткової інформації про те, як видалити рядки.

http://support.microsoft.com/kb/139444

Редагувати: Як згадували інші користувачі, перед тим, як використовувати підхід у посиланні вище, має бути критерій для визначення способу визначення "перших рядків". Виходячи з цього, вам потрібно буде використовувати замовлення за пунктом та підзапит, якщо це потрібно. Якщо ви можете опублікувати деякі зразкові дані, це дійсно допоможе.


42

Ви згадуєте "перший", тому я припускаю, що у вас є якесь замовлення на ваші дані. Припустимо, що ваші дані упорядковані в якомусь полі ID.

Цей SQL повинен отримати вам дублікати записів, крім першої. В основному він вибирає всі рядки, для яких існує інший рядок з (а) тими ж полями та (b) нижчим ідентифікатором. Продуктивність не буде великою, але це може вирішити вашу проблему.

SELECT A.ID, A.field1, A.field2, A.field3
  FROM myTable A
 WHERE EXISTS (SELECT B.ID
                 FROM myTable B
                WHERE B.field1 = A.field1
                  AND B.field2 = A.field2
                  AND B.field3 = A.field3
                  AND B.ID < A.ID)

17

Це цікаве рішення з SQL Server 2005, яке мені подобається. Я припускаю, що під "для кожного запису, окрім першого", ви маєте на увазі, що є ще один стовпець "id", який ми можемо використовувати, щоб визначити, який рядок "перший".

SELECT id
    , field1
    , field2
    , field3
FROM
(
    SELECT id
        , field1
        , field2
        , field3
        , RANK() OVER (PARTITION BY field1, field2, field3 ORDER BY id ASC) AS [rank]
    FROM table_name
) a
WHERE [rank] > 1

Щойно помітив тег SQL Server 2008. Радий, що моя пропозиція все ще діє.
Нік Ваккаро

1
Відмінне рішення, оскільки воно також повертає рядки, які потрібно буде видалити з відповідної таблиці
Realto619

1
це допомагає мислити список
розділів за розділом

6

Щоб побачити повторювані значення:

with MYCTE  as (
    select row_number() over ( partition by name  order by name) rown, *
    from tmptest  
    ) 
select * from MYCTE where rown <=1

3

Якщо ви використовуєте SQL Server 2005 або новішу версію (а теги для вашого питання вказують на SQL Server 2008), ви можете використовувати функції ранжування для повернення дублікатів записів після першої, якщо використання приєднань з певних причин є менш бажаним або недоцільним. Наступний приклад показує це в дії, де він також працює з нульовими значеннями в розглянутих стовпцях.

create table Table1 (
 Field1 int,
 Field2 int,
 Field3 int,
 Field4 int 
)

insert  Table1 
values    (1,1,1,1)
        , (1,1,1,2)
        , (1,1,1,3)
        , (2,2,2,1)
        , (3,3,3,1)
        , (3,3,3,2)
        , (null, null, 2, 1)
        , (null, null, 2, 3)

select    *
from     (select      Field1
                    , Field2
                    , Field3
                    , Field4
                    , row_number() over (partition by   Field1
                                                      , Field2
                                                      , Field3
                                         order by       Field4) as occurrence
          from      Table1) x
where     occurrence > 1

Зауважте після запуску цього прикладу, що перший запис з кожної "групи" виключається, а записи з нульовими значеннями обробляються належним чином.

Якщо у вас немає стовпця для замовлення записів у групі, ви можете використовувати стовпці розділення як стовпці порядку.


1
CREATE TABLE #tmp
(
    sizeId Varchar(MAX)
)

INSERT  #tmp 
    VALUES ('44'),
        ('44,45,46'),
        ('44,45,46'),
        ('44,45,46'),
        ('44,45,46'),
        ('44,45,46'),
        ('44,45,46')


SELECT * FROM #tmp
DECLARE @SqlStr VARCHAR(MAX)

SELECT @SqlStr = STUFF((SELECT ',' + sizeId
              FROM #tmp
              ORDER BY sizeId
              FOR XML PATH('')), 1, 1, '') 


SELECT TOP 1 * FROM (
select items, count(*)AS Occurrence
  FROM dbo.Split(@SqlStr,',')
  group by items
  having count(*) > 1
  )K
  ORDER BY K.Occurrence DESC    

0

спробуйте цей запит, щоб мати кількість підрозділів sepratley для кожного оператора SELECT:

select field1,count(field1) as field1Count,field2,count(field2) as field2Counts,field3, count(field3) as field3Counts
from table_name
group by field1,field2,field3
having count(*) > 1
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.