Выберите оператор, чтобы найти дубликаты в определенных полях

Можете ли вы помочь мне с операторами SQL найти дубликаты в нескольких полях?

Например, в псевдокоде:

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

и из приведенного выше утверждения, если есть несколько вхождений, я хотел бы выбрать каждую запись, кроме первой.

Ответ 1

Чтобы получить список полей, для которых есть несколько записей, вы можете использовать..

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

Посмотрите эту ссылку для получения дополнительной информации о том, как удалить строки.

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

Изменить: как упомянули другие пользователи, должен быть критерий для определения того, как вы определяете "первые строки", прежде чем использовать подход в приведенной выше ссылке. На основании этого вам нужно будет использовать предложение order by и дополнительный запрос, если это необходимо. Если вы можете опубликовать некоторые примеры данных, это действительно поможет.

Ответ 2

Вы упоминаете "первый", поэтому я предполагаю, что у вас есть какой-то порядок в ваших данных. Предположим, что ваши данные упорядочены некоторым полем ID.

Этот SQL должен получить дубликаты записей, кроме первого. Он в основном выбирает все строки, для которых другая строка содержит (a) те же поля и (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)

Ответ 3

Это интересное решение с 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

Ответ 4

Чтобы увидеть дублирующее значение

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

                ) 
              select * from MYCTE where rown <=1

Ответ 5

Если вы используете 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

Обратите внимание, что после запуска этого примера исключена первая запись из каждой "группы" и что записи с нулевыми значениями обрабатываются правильно.

Если у вас нет столбца, доступного для заказа записей внутри группы, вы можете использовать столбцы "по столбцам" как столбцы порядка.

Ответ 6

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