【问题标题】:SQL Server: How can I determine if a composite of several fields in a row are unique?SQL Server:如何确定一行中多个字段的组合是否唯一?
【发布时间】:2014-06-12 19:14:27
【问题描述】:

我正在尝试在 T-SQL 中做这样的事情:

SELECT ID 
FROM table
WHERE (ID, Firstname, Lastname) IN 
(SELECT ID, Firstname, Lastname
FROM table
GROUP BY ID, Firstname, Lastname
HAVING (COUNT(ID) > 1) AND (COUNT(Firstname) > 1) AND (COUNT(Lastname) > 1))

基本上,如果有一行的 ID、Firstname 和 Lastname 的值在另一行中同时重复,我想选择它的 ID。我了解have子句的设置方式,它不会那样工作,但请耐心等待。我希望它像这样工作:

ID Firstname Lastname age
-------------------------
01 Bob       Smith    25
01 Bob       Smith    35
03 Bob       Smith    25
03 Mike      Smith    25
03 Bob       Baloney  25

在上面的示例中,仅选择了“01”,因为它与三列中它下方的字段匹配。 '03' 与任何两列中的 ID、名字或姓氏都不完全匹配,因此不会被选中。此外,它是否匹配年龄也没关系,因为我不在乎年龄。

如果我添加这样的列:

ID Firstname Lastname age
-------------------------
01 Bob       Smith    25
01 Bob       Smith    35
03 Bob       Smith    25
03 Mike      Smith    25
03 Bob       Baloney  25
03 Mike      Smith    32

THEN '03' 也将被选中,因为它现在匹配三个相关字段,其中记录在其上方两行。

我已经看到使用派生表来弥补对复合 WHERE-IN 子句支持不足的答案,但我不确定如何将唯一性的想法添加到子查询中。

非常感谢!

【问题讨论】:

    标签: sql sql-server unique where composite-key


    【解决方案1】:

    您可以使用HAVING COUNT(*) > 1 查找具有多个条目的所有组合:

    SELECT DISTINCT ID 
    FROM (SELECT ID,FirstName,LastName
          FROM table1
          GROUP BY ID,FirstName,LastName
          HAVING COUNT(*) > 1
          )sub
    

    演示:SQL Fiddle

    更新:如果您想将上述结果用于UPDATE 表格,您可以通过多种方式进行操作,但使用COUNT() 更改识别这些倍数的方式可能更容易使用OVER() 子句或ROW_NUMBER() 函数,根据您想要更新数据的方式,您可以然后UPDATEcte

    ;WITH cte AS (SELECT *, COUNT(*) OVER(PARTITION BY ID,FirstName,LastName) AS CT
                          , ROW_NUMBER() OVER(PARTITION BY ID,FirstName,LastName ORDER BY ID) AS RN
                  FROM Table1)
    UPDATE cte
    SET Somefield = 'SomeValue'
    WHERE CT > 1  -- RN > 1
    

    观察两个函数的行为(添加到上面的sql fiddle链接):

    ;WITH cte AS (SELECT *, COUNT(*) OVER(PARTITION BY ID,FirstName,LastName) AS CT
                          , ROW_NUMBER() OVER(PARTITION BY ID,FirstName,LastName ORDER BY ID) AS RN
                  FROM Table2)
    SELECT *
    FROM cte  
    

    【讨论】:

    • 当表中有更多(Address1,Address2,...)列时怎么办?
    • @SimchaKhabinsky 年龄是第 4 列,其他列不会改变行为,如果只需要 ID 值,并且某些匹配字段有多个条目,那么这是有效的。
    • @GoatCO 。 . .我认为子查询足以回答问题。
    • 现在,如果我想使用该信息来更新同一个表中的字段,更新语句中的多个内部联接是否最好?
    • @HarisKhan 不需要多个内部连接,你能举个例子说明你想更新什么吗?
    猜你喜欢
    • 2016-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-17
    相关资源
    最近更新 更多