найти повторяющиеся строки в таблице при вставке - PullRequest
1 голос
/ 23 июня 2011

У меня есть таблица, подобная приведенной ниже

ID   Value
----------
1    A
2    B
3    C
3    C
4    A
4    D
5    A
5    C
5    D

Я хочу запрос или хранимую процедуру, которая определит, существует ли уже комбинация, если я попытаюсь вставить комбинацию значений того же типа.Например: если я пытаюсь вставить

6   A
6   D

, дайте мне знать, что уже существует такая же комбинация с идентификатором 4. Возможно ли это в MSSQL?

Несколько комментариев: Когда яя пытаюсь вставить новые значения, идентификатор будет новым, поэтому мы не можем найти в таблице дублирующиеся строки с идентификатором и комбинацией значений.Мне нужен способ для поиска дубликатов значений с той же комбинацией значений идентификатора.

В приведенном выше примере, когда я пытаюсь вставить

6   A
6   D

Это пойдет и искать в таблицеесли существуют какие-либо строки для значений с A и D, имеющих одинаковый идентификатор в приведенной выше таблице, то существует идентификатор 4, поэтому он должен сообщить мне, что при попытке вставить это есть дублирующаяся запись.

Ответы [ 5 ]

2 голосов
/ 23 июня 2011

Это даст вам идентификаторы из @T, которые уже имеют комбинацию значений, предоставленных в @ NewValues.

declare @T table (ID int, Value char(1))
insert into @T values
(1,    'A'),(2,    'B'),(3,    'C'),(3,    'C'),
(4,    'A'),(4,    'D'),(5,    'A'),(5,    'C'),
(5,    'D')

declare @NewValues table(ID int, Value char(1))
insert into @NewValues values (6,    'A'), (6,    'D')

select T.ID
from @T as T
  inner join @NewValues as N
    on T.Value = N.Value
group by T.ID
having count(*) = (select count(*) from @NewValues)

Результат:

ID
4
5

Если вам нужны только точные совпаденияЭто означает, что ID = 5 не будет возвращено, потому что он также имеет одну строку со значением = 'C', вы можете использовать это вместо этого.

select T.ID
from @T as T
  left outer join @NewValues as N
    on T.Value = N.Value
group by T.ID
having count(N.Value) = (select count(*) from @NewValues) and 
       count(*) = (select count(*) from @NewValues)

Я вижу, что у вас есть (3, 'C') и(3, 'C') в вашей таблице.Если вы хотите обнаружить это с помощью ввода (6, 'C') и (6, 'C'), вам нужен этот запрос.

select T.ID
from @T as T
  left outer join (select distinct Value
                   from @NewValues) as N
    on T.Value = N.Value
group by T.ID
having count(N.Value) = (select count(*) from @NewValues) and 
       count(*) = (select count(*) from @NewValues)

Заполните `@NewValues?таблица с функцией разделения строк.

-- Paramenter to SP
declare @ParamID int = 6
declare @ParamValues varchar(100) = 'A,D'

declare @NewValues table(ID int, Value char(1))
insert into @NewValues
select @ParamID, s
from dbo.Split(',', @ParamValues)
0 голосов
/ 23 июня 2011

Концепция универсальное количественное определение , реляционный оператор называется деление , широко известный как «поставщик, который поставляет все детали» .

Поскольку вы не считаете ID = 5 представлением дубликата, вам следует обратить внимание на точное деление (т.е. без остатка), и пустой делитель, вероятно, не является проблемой в вашемдело.

Полезная статья: О том, как сделать реляционное деление понятным

0 голосов
/ 23 июня 2011

Вы должны использовать команду MERGE, см. Здесь http://pratchev.blogspot.com/2008/03/upsert-and-more-with-merge.html

0 голосов
/ 23 июня 2011

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

0 голосов
/ 23 июня 2011

Да, это возможно.Один из способов сделать это - определить первичный ключ как (ID, Value).Это вызовет исключение каждый раз, когда кто-то пытается вставить существующий кортеж (ID, значение).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...