Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Поиск дубликатов НАБОРА записей  [new]
Dmitry V. Liseev
Member [заблокирован]

Откуда: Санкт-Петербург
Сообщений: 5489
Появилась задачка проверки данных на дубликаты. Но не одной записи, а сразу нескольких. Не важно где именно и сколько. Важно только ЕСТЬ или НЕТ.

SET NOCOUNT ON;

CREATE TABLE #t1
(
	id INT,
	a INT,
	b INT
);
-- Источник для сравнения.
INSERT INTO #t1 VALUES(1, 5, 7);
INSERT INTO #t1 VALUES(1, 8, 2);
-- Одно совпадение.
INSERT INTO #t1 VALUES(2, 8, 2);
-- Одно совпадение.
INSERT INTO #t1 VALUES(3, 5, 7);
-- Полное совпадение.
INSERT INTO #t1 VALUES(4, 5, 7);
INSERT INTO #t1 VALUES(4, 8, 2);
-- Одно лишнее.
INSERT INTO #t1 VALUES(5, 5, 7);
INSERT INTO #t1 VALUES(5, 9, 7);
INSERT INTO #t1 VALUES(5, 8, 2);

DECLARE @CurrentAmount INT, @SourceKey INT;

SET @SourceKey = 1; -- id источника для сравнения.

SELECT @CurrentAmount = COUNT(*) FROM #t1 WHERE id = @SourceKey;

IF EXISTS
(
	SELECT *
	FROM #t1 pe1
	JOIN #t1 pe2 ON pe2.a = pe1.a AND pe2.b = pe1.b
		AND pe1.id = @SourceKey AND pe2.id <> @SourceKey
	GROUP BY pe2.id
	HAVING COUNT(*) = @CurrentAmount
		AND (SELECT COUNT(*) FROM #t1 WHERE id = pe2.id) = @CurrentAmount
) PRINT N'Дубликаты есть'
ELSE PRINT N'Дубликатов нет'

DROP TABLE #t1;
Может, есть более оптимальный способ?
16 июн 14, 17:54    [16171316]     Ответить | Цитировать Сообщить модератору
 Re: Поиск дубликатов НАБОРА записей  [new]
Гигабайт Мегабайтович Килобайтов
Member [заблокирован]

Откуда:
Сообщений: 5975
версия какая?

если "дубликатов" не много - простой group by по всем полям с каунтом,

если много - то посмотреть в сторону EXCEPT|INTERSECT
16 июн 14, 18:00    [16171353]     Ответить | Цитировать Сообщить модератору
 Re: Поиск дубликатов НАБОРА записей  [new]
Dmitry V. Liseev
Member [заблокирован]

Откуда: Санкт-Петербург
Сообщений: 5489
Гигабайт Мегабайтович Килобайтов
версия какая?

если "дубликатов" не много - простой group by по всем полям с каунтом,

если много - то посмотреть в сторону EXCEPT|INTERSECT
Версия 2008 R2.
16 июн 14, 18:27    [16171463]     Ответить | Цитировать Сообщить модератору
 Re: Поиск дубликатов НАБОРА записей  [new]
a_voronin
Member

Откуда: Москва
Сообщений: 4893
Dmitry V. Liseev,


SET NOCOUNT ON;

CREATE TABLE #t1
(
	id INT,
	a INT,
	b INT
);
-- Источник для сравнения.
INSERT INTO #t1 VALUES(1, 5, 7);
INSERT INTO #t1 VALUES(1, 8, 2);
-- Одно совпадение.
INSERT INTO #t1 VALUES(2, 8, 2);
-- Одно совпадение.
INSERT INTO #t1 VALUES(3, 5, 7);
-- Полное совпадение.
INSERT INTO #t1 VALUES(4, 5, 7);
INSERT INTO #t1 VALUES(4, 8, 2);
-- Одно лишнее.
INSERT INTO #t1 VALUES(5, 5, 7);
INSERT INTO #t1 VALUES(5, 9, 7);
INSERT INTO #t1 VALUES(5, 8, 2);
INSERT INTO #t1 VALUES(5, 8, 2);

DECLARE @CurrentAmount INT, @SourceKey INT;

SET @SourceKey = 1; -- id источника для сравнения.

SELECT @CurrentAmount = COUNT(*) FROM #t1 WHERE id = @SourceKey;

IF EXISTS
(
	SELECT *
	FROM #t1 pe1
	JOIN #t1 pe2 ON pe2.a = pe1.a AND pe2.b = pe1.b
		AND pe1.id = @SourceKey AND pe2.id <> @SourceKey
	GROUP BY pe2.id
	HAVING COUNT(*) = @CurrentAmount
		AND (SELECT COUNT(*) FROM #t1 WHERE id = pe2.id) = @CurrentAmount
) PRINT N'Дубликаты есть'
ELSE PRINT N'Дубликатов нет';


	WITH T AS 
	(
		SELECT t.*, ROW_NUMBER() OVER (PARTITION BY id, a, b ORDER BY id, a, b) AS RN
		FROM #t1 t									 
	)
	SELECT DISTINCT id, N'Дубликаты есть' FROM T 
	WHERE RN > 1

DROP TABLE #t1;
16 июн 14, 18:48    [16171545]     Ответить | Цитировать Сообщить модератору
 Re: Поиск дубликатов НАБОРА записей  [new]
Dmitry V. Liseev
Member [заблокирован]

Откуда: Санкт-Петербург
Сообщений: 5489
Надо строить неповторяющиеся маршруты в графе. Если в двух маршрутах список рёбер совпадает, то они одинаковы. Такой маршрут снова добавлять не надо.
16 июн 14, 19:08    [16171613]     Ответить | Цитировать Сообщить модератору
 Re: Поиск дубликатов НАБОРА записей  [new]
aleks2
Guest
Dmitry V. Liseev
Надо строить неповторяющиеся маршруты в графе. Если в двух маршрутах список рёбер совпадает, то они одинаковы. Такой маршрут снова добавлять не надо.

Ну дык, построй полный маршрут FOR XML path('') и сравнивай скока угодно.
16 июн 14, 19:48    [16171734]     Ответить | Цитировать Сообщить модератору
 Re: Поиск дубликатов НАБОРА записей  [new]
Кот Матроскин
Member

Откуда: Москва
Сообщений: 8933
a_voronin,

Вот на таком наборе Ваш запрос сфейлит
INSERT INTO #t1 VALUES(1, 5, 7);
INSERT INTO #t1 VALUES(1, 8, 2);
-- двойное совпадение  одной строки
INSERT INTO #t1 VALUES(2, 8, 2);
INSERT INTO #t1 VALUES(2, 8, 2);
-- Одно совпадение.
INSERT INTO #t1 VALUES(3, 5, 7);
-- .
INSERT INTO #t1 VALUES(4, 5, 7);
--INSERT INTO #t1 VALUES(4, 8, 2);


Надо примерно так
...
IF EXISTS
(
	SELECT pe2.id
	FROM #t1 pe1
	JOIN #t1 pe2 ON pe2.a = pe1.a AND pe2.b = pe1.b
		AND pe1.id = @SourceKey AND pe2.id <> @SourceKey
   
	GROUP BY pe2.id, pe1.id - pe2.id
	HAVING COUNT(distinct pe1.a*1000000 + pe2.b /*в реальном коде тут будет некая уникальная функция от A и B*/) = @CurrentAmount
		AND (SELECT COUNT(*) FROM #t1 WHERE id = pe2.id) = @CurrentAmount
) PRINT N'Дубликаты есть'
ELSE PRINT N'Дубликатов нет';
16 июн 14, 20:03    [16171774]     Ответить | Цитировать Сообщить модератору
 Re: Поиск дубликатов НАБОРА записей  [new]
Dmitry V. Liseev
Member [заблокирован]

Откуда: Санкт-Петербург
Сообщений: 5489
Кот Матроскин
a_voronin,

Вот на таком наборе Ваш запрос сфейлит
INSERT INTO #t1 VALUES(1, 5, 7);
INSERT INTO #t1 VALUES(1, 8, 2);
-- двойное совпадение  одной строки
INSERT INTO #t1 VALUES(2, 8, 2);
INSERT INTO #t1 VALUES(2, 8, 2);
-- Одно совпадение.
INSERT INTO #t1 VALUES(3, 5, 7);
-- .
INSERT INTO #t1 VALUES(4, 5, 7);
--INSERT INTO #t1 VALUES(4, 8, 2);


Надо примерно так
...
IF EXISTS
(
	SELECT pe2.id
	FROM #t1 pe1
	JOIN #t1 pe2 ON pe2.a = pe1.a AND pe2.b = pe1.b
		AND pe1.id = @SourceKey AND pe2.id <> @SourceKey
   
	GROUP BY pe2.id, pe1.id - pe2.id
	HAVING COUNT(distinct pe1.a*1000000 + pe2.b /*в реальном коде тут будет некая уникальная функция от A и B*/) = @CurrentAmount
		AND (SELECT COUNT(*) FROM #t1 WHERE id = pe2.id) = @CurrentAmount
) PRINT N'Дубликаты есть'
ELSE PRINT N'Дубликатов нет';
В моей задаче строки не дублируются. Сорри, что сразу не уточнил. Ребро не может два раза входить в один маршрут в графе.
16 июн 14, 20:39    [16171897]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить