35

suppose I have following sql table

    objid  firstname lastname active
     1       test      test     0
     2       test      test     1
     3       test1     test1    1
     4       test2     test2    0
     5       test2     test2    0
     6       test3     test3    1

Now, the result I am interested in is as follows:

     objid  firstname lastname active
     1       test      test     0
     2       test      test     1
     4       test2     test2    0
     5       test2     test2    0

How can I achieve this? I have tried the following query,

select firstname,lastname from table
group by firstname,lastname
having count(*) > 1

But this query gives results like

    firstname  lastname
     test        test
     test2       test2
0

11 Answers 11

62

You've found your duplicated records but you're interested in getting all the information attached to them. You need to join your duplicates to your main table to get that information.

select *
  from my_table a
  join ( select firstname, lastname 
           from my_table 
          group by firstname, lastname 
         having count(*) > 1 ) b
    on a.firstname = b.firstname
   and a.lastname = b.lastname

This is the same as an inner join and means that for every record in your sub-query, that found the duplicate records you find everything from your main table that has the same firstseen and lastseen combination.

You can also do this with in, though you should test the difference:

select *
  from my_table a
 where ( firstname, lastname ) in   
       ( select firstname, lastname 
           from my_table 
          group by firstname, lastname 
         having count(*) > 1 )

Further Reading:

Sign up to request clarification or add additional context in comments.

11 Comments

does this syntax work in sql server? where ( firstname, lastname ) in ( select firstname, lastname from my_table group by firstname, lastname having count(*) > 1 )
Have you run it @nee21? What problems did you have?
Yes, I get this error: Msg 4145, Level 15, State 1, Line 161 An expression of non-boolean type specified in a context where a condition is expected, near ','. I am not sure if am missing anything.
Hi @Ben, did u get a chance to check this?
i don't think it works on sql server @Ben. op put the sql server 2008 as label
|
8
SELECT DISTINCT t1.*
FROM myTable AS t1
INNER JOIN myTable AS t2
  ON t1.firstname = t2.firstname
  AND t1.lastname = t2.lastname
  AND t1.objid <> t2.objid

This will output every row which has a duplicate, basing on firstname and lastname.

2 Comments

instead of id you might have meant objid
Additionally, if you don't distinct the results you'll get duplicates.
6

Here's a little more legible way to do Ben's first answer:

WITH duplicates AS (
   select    firstname, lastname
   from      my_table
   group by  firstname, lastname
   having    count(*) > 1
)
SELECT    a.*
FROM      my_table   a
JOIN      duplicates b ON (a.firstname = b.firstname and a.lastname = b.lastname)

7 Comments

Wouldn't a simple join (like in my answer) be faster than joining to a grouped temporary table?
@Shedal: they should be the same thing. A subquery is a temporary table. The above is a way of simplifying reading the SQL. By doing your declaring/defining your subqueries up front, you're able to concentrate on the heart of the SQL that follows
@Shedal, it depends. If there's an index on firstname, lastname for instance ( I +1'd you though as it's just a different way of doing things ).
@Ben well there should be an index on firstname, lastname anyway, for both queries to run fast.
@Shedal, the sub-query will only use the index though, the join will have to either use two indexes ( unless it's indexed on obj_id, fn, ln) or enter the table. Plus there's no need to do a distinct. Without testing and knowing the selectivity of the columns it's impossible to tell which'll be faster.
|
6
SELECT user_name,email_ID 
FROM User_Master WHERE 
email_ID 
in (SELECT email_ID 
FROM User_Master GROUP BY 
email_ID HAVING COUNT(*)>1) 

enter image description here

1 Comment

While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value.
1

nice option get all duplicated value from tables

 select * from Employee where Name in (select Name from Employee group by Name having COUNT(*)>1)

Comments

1

This is the easiest way:

SELECT * FROM yourtable a WHERE EXISTS (SELECT * FROM yourtable b WHERE a.firstname = b.firstname AND a.secondname = b.secondname AND a.objid <> b.objid)

Comments

1

If you want to print all duplicate IDs from the table:

select * from table where id in (select id from table group By id having count(id)>1)

Comments

1

I'm surprised that there is no answer using Window function. I just came across this use case and this helped me.

select t.objid, t.firstname, t.lastname, t.active
from
(
select t.*, count(*) over (partition by firstname, lastname) as cnt
from my_table t
) t
where t.cnt > 1;

Fiddle - https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=c0cc3b679df63c4d7d632cbb83a9ef13


The format goes like

select
    tbl.relevantColumns
from
(
    select t.*, count(*) over (partition by key_columns) as cnt
    from desiredTable t
) as tbl
where tbl.cnt > 1;

This format selects whatever columns you require from the table (sometimes all columns) where the count > 1 for the key_columns being used to identify the duplicate rows. key_columns can be any number of columns.

Comments

0

This answer may not be great one, but I think it is simple to understand.

SELECT * FROM table1 WHERE (firstname, lastname) IN ( SELECT firstname, lastname FROM table1 GROUP BY firstname, lastname having count() > 1);

Comments

0

This Query returns dupliacates

SELECT * FROM (
  SELECT  a.* 
    FROM table a 
    WHERE (`firstname`,`lastname`) IN (
        SELECT `firstname`,`lastname` FROM table 
        GROUP BY `firstname`,`lastname` HAVING COUNT(*)>1       
        )  
    )z WHERE z.`objid` NOT IN (
        SELECT MIN(`objid`) FROM table 
        GROUP BY `firstname`,`lastname` HAVING COUNT(*)>1
        )                                         

Comments

0

Please try

WITH cteTemp AS (
  SELECT EmployeeID, JoinDT,
     row_number() OVER(PARTITION BY EmployeeID, JoinDT ORDER BY EmployeeID) AS [RowFound]
  FROM dbo.Employee 
)
SELECT * FROM cteTemp WHERE [RowFound] > 1 ORDER BY JoinDT

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.