【问题标题】:findout duplicate rows in a table while inserting插入时找出表中的重复行
【发布时间】:2011-06-23 05:03:33
【问题描述】:

我有一张像下面这样的表格

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

如果我尝试插入相同类型的值组合,我想要一个查询或存储过程来识别是否已经存在组合。 例如:如果我想插入

6   A
6   D

会让我知道已经存在与 id 4 相同的组合。 在 MSSQL 中可以吗?

几条评论:当我尝试插入新值时,Id 将是新的,因此我们无法在表中搜索具有 id、值组合的重复行。 我需要一种方法来搜索具有相同 id 值组合的重复值。

在上面的示例中,当我尝试插入时

6   A
6   D

如果上表中存在具有相同 ID 的 A 和 D 的值的任何行,它将去表中搜索,因此它应该让我知道当我有重复的条目时尝试插入它。

【问题讨论】:

  • 可以,但在存储过程中使用位编码
  • 你希望它如何让你知道?
  • 可以是存储过程MSSQL2005
  • 如果有人试图插入一对(4, C)怎么办?这将使 ID 4 的组合与 ID 5 的组合相同。在您的项目中可以进行这样的插入吗?是否应该被拦截和报告?
  • 是的,在这种情况下,如插入 4 C 不应该允许,因为它会再次匹配 5- A C D 的组合。它也应该报告。

标签: sql sql-server tsql


【解决方案1】:

这将为您提供来自@T 的 ID,这些 ID 已经具有 @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,因为它也有一行 Value='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)

【讨论】:

  • 根据我对问题的理解,现有组合应该完全匹配。例如,ID 5 无法匹配,因为它包含新组合没有的“额外”项目“C”。所以它可能应该是完全加入,就像@Alex Aza 的回答一样。但这只是我的理解。
  • @Andriy - 添加了我相信会解决这个问题的第二个版本。
  • @Mikael:是的,如果我的假设是正确的,那么您的第二个查询应该可以正确找到重复项。但是,请查看我添加到您的答案中的具有完全连接的替代版本。 (不同意请回滚。)
  • 哇!谢谢你的回答。我们可以在没有 newTable 的情况下使用它,就像在我插入将值的组合传递给存储过程并在存在具有相同组合的 ID 时返回我之前一样。
  • @Andriy - 您添加的完整外部联接版本也将返回 ID=1。
【解决方案2】:

是的,这是可能的。一种方法是将主键定义为 (ID,Value)。每次有人尝试插入现有的 (ID,Value) 元组时,都会引发异常。

【讨论】:

    【解决方案3】:

    您应该使用 MERGE 命令,请参阅此处http://pratchev.blogspot.com/2008/03/upsert-and-more-with-merge.html

    【讨论】:

    • 在该链接中找不到与此相关的任何内容。
    【解决方案4】:

    在插入之前,查询与该 id 组合的所有字母。然后将要插入的字母添加到该列表中,然后检查每个 Id 是否存在与列表中所有字母有关系的 Id。 如果至少有一个,则通知用户。

    【讨论】:

      【解决方案5】:

      概念是万能量化,关系算子称为division,俗称"the supplier who supplies all parts"

      因为您不认为 ID = 5 代表重复,您应该查看 exact division(即没有余数)并且空除数在您的情况下可能不是问题。

      有用的文章:On Making Relational Division Comprehensible

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-05-06
        • 2015-04-18
        • 1970-01-01
        • 2023-03-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-16
        相关资源
        最近更新 更多