Выберите оператор, чтобы найти дубликаты в определенных полях
Можете ли вы помочь мне с операторами 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