Question

given below table:

+----+---------+-----------+-------------+-------+
| ID |  NAME   | LAST NAME |    PHONE    | STATE |
+----+---------+-----------+-------------+-------+
|  1 | James   | Vangohg   | 04333989878 | NULL  |
|  2 | Ashly   | Baboon    | 09898788909 | NULL  |
|  3 | James   | Vangohg   | 04333989878 | NULL  |
|  4 | Ashly   | Baboon    | 09898788909 | NULL  |
|  5 | Michael | Foo       | 02933889990 | NULL  |
|  6 | James   | Vangohg   | 04333989878 | NULL  |
+----+---------+-----------+-------------+-------+

I want to use MS SQL to find and update duplicate (based on name, last name and number) but only the earlier one(s). So desired result for above table is:

+----+---------+-----------+-------------+-------+
| ID |  NAME   | LAST NAME |    PHONE    | STATE |
+----+---------+-----------+-------------+-------+
|  1 | James   | Vangohg   | 04333989878 | DUPE  |
|  2 | Ashly   | Baboon    | 09898788909 | DUPE  |
|  3 | James   | Vangohg   | 04333989878 | DUPE  |
|  4 | Ashly   | Baboon    | 09898788909 | NULL  |
|  5 | Michael | Foo       | 02933889990 | NULL  |
|  6 | James   | Vangohg   | 04333989878 | NULL  |
+----+---------+-----------+-------------+-------+
Was it helpful?

Solution

This query uses a CTE to apply a row number, where any number > 1 is a dupe of the row with the highest ID.

;WITH x AS 
(
  SELECT ID,NAME,[LAST NAME],PHONE,STATE,
    ROW_NUMBER() OVER (PARTITION BY NAME,[LAST NAME],PHONE ORDER BY ID DESC) 
  FROM dbo.YourTable
)
UPDATE x SET STATE = CASE rn WHEN 1 THEN NULL ELSE 'DUPE' END;

Of course, I see no reason to actually update the table with this information; every time the table is touched, this data is stale and the query must be re-applied. Since you can derive this information at run-time, this should be part of a query, not constantly updated in the table. IMHO.

OTHER TIPS

Try this statement.

LAST UPDATE:

update t1
set
t1.STATE = 'DUPE'

from 

TableName t1

join 
(
    select name, last_name, phone, max(id) as id, count(id) as cnt
    from
    TableName
    group by name, last_name, phone
    having count(id) > 1
) t2 on ( t1.name = t2.name and t1.last_name = t2.last_name and t1.phone = t2.phone and t1.id < t2.id)

If my understanding of your requirements is correct, you want to update all of the STATE values to DUPE when there exists another row with a higher ID value that has the same NAME and LAST NAME. If so, use this:

update t set STATE = (case when sorted.RowNbr = 1 then null else 'DUPE' end)

from yourtable t

join (select 
          ID, 
          row_number() over 
              (partition by name, [last name], phone order by id desc) as RowNbr from yourtable) 

     sorted on sorted.ID = t.ID
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top