Click here to Skip to main content
15,884,176 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,

I have a query below

declare @tbl table (id int identity(1,1),sname varchar(10),marks int)
insert into @tbl values('A',10),('B',10),('A',10),('B',40),('C',10),('D',15),('A',9)
select row_number()over(partition by sname,marks order by marks)sno,sname,marks from @tbl

my result is:
sno sname marks
1 A 9
1 A 10
2 A 10
1 B 10
1 B 40
1 C 10
1 D 15

But I want to only second and third rows as these are duplicate records. i want all duplicate records irrespective of repeatation.

Please suggest

Thanks

What I have tried:

duplicates records elimination
Posted
Updated 25-Jul-18 23:07pm

Given that sno is always going to be 1 (because you are partitioning by sname AND marks) you could simplify this to
SQL
select distinct 1 as sno,sname, marks from @tbl
The key point being that it is your introduction of the row_number() that is actually causing the issue.

But I suspect you want sno to be something meaningful (correct me if I'm wrong)

If you want it to show the number of the mark per name then use
SQL
select row_number() over (partition by sname order by sname,marks) as sno, sname, marks
FROM (select distinct 1 as sno,sname, marks from @tbl) A
which will give you
sno	sname	mark
1	A	9
2	A	10
1	B	10
2	B	40
1	C	10
1	D	15
If you want to give each row a number then remove the partition altogether
SQL
select row_number() over (order by sname,marks) as sno, sname, marks
FROM (select distinct sname, marks from @tbl) A
sno	sname	mark
1	A	9
2	A	10
3	B	10
4	B	40
5	C	10
6	D	15


------------------ EDIT AFTER OP COMMENT ---------------

To only get the lines that are duplicated there are two ways you could try:

1. To get the sname and marks and the number of duplications try this
SQL
select sname, marks, max(sno) as numberOfDups from 
(select row_number() over (partition by sname, marks order by sname,marks) as sno, sname, marks
FROM  @tbl) A
where sno > 1
group by sname, marks


2. To get the full list of items that have duplicates try this:
SQL
;with cte as
(
	select row_number() over (partition by sname, marks order by sname,marks) as sno, sname, marks
	from @tbl
)
select * 
from cte 
inner join (select sname, marks, max(sno) as numberOfDup from cte where sno > 1 group by sname, marks) B on cte.sname = B.sname AND cte.marks = B.marks
The key is the INNER JOIN on a sub-query looking at the CTE a second time. It's not just a simple "give me the rows where sno > 1" - the join ensures that while we don't see the non-duplicated rows we do see all the rows where there has been a duplicate - i.e. A 10 where sno - 1 AND 2, not just 2

------------------ EDIT AFTER ANOTHER OP COMMENT ---------------

Introducing other columns which must be taken into account - the joins take "much time for the on conditions

Test data:
SQL
declare @tbl table (id int identity(1,1),sname varchar(10),marks int, other int)
insert into @tbl values('A',10,1),('B',10,1),('A',10,1),('B',40,1),('C',10,2),('D',15,2),('A',9,1), ('A',10,2)
My original solution would return
1	A	10	2	3
2	A	10	1	3
3	A	10	1	3
Which is incorrect when taking into account the other column.

We can use Checksum [^] to "combine" all of the columns that are relevent e.g.
SQL
;with cte1 as 
(
	select checksum(sname, marks, other) as sno, sname, marks, other from @tbl
)
select sname, marks, other
from cte1
inner join (select checksum(sname, marks, other) as sno from @tbl group by checksum(sname, marks, other) having count(*) > 1) A on cte1.sno = A.sno
results
A	10	1
A	10	1
 
Share this answer
 
v3
Comments
Member 13867163 26-Jul-18 5:22am    
If I take Sno=1 then I get unique records ignoring duplicates

If I take Sno>1 then I get the records which having duplicates (in this case, A will come because it is having duplicates)

But what is needed is I want to get A name with how many times it is repeated like below.
Sno Sname Marks
1 A 10
2 A 10
remaining records dont want.
CHill60 26-Jul-18 5:24am    
Ah ... so you only want to see records that have duplicates and how many duplicates there were? Give me a few minutes
CHill60 26-Jul-18 5:43am    
Sorry about that - I've updated my solution
Member 13867163 26-Jul-18 5:51am    
Great..
Thank you
this works fine
CHill60 26-Jul-18 6:21am    
Great - you can "Accept" the solution if you would - this indicates to other visitors that this was the one that worked (rather than them having to read the comments)
declare @tbl table (id int identity(1,1),sname varchar(10),marks int)
insert into @tbl values('A',10),('B',10),('A',10),('B',40),('C',10),('D',15),('A',9)
select * from (
select row_number()over(partition by sname,marks order by marks)sno,sname,marks from @tbl) as a where sno=1



declare @tbl table (id int identity(1,1),sname varchar(10),marks int)
insert into @tbl values('A',10),('B',10),('A',10),('B',40),('C',10),('D',15),('A',9)

;with cte as 
(
select row_number()over(partition by sname,marks order by marks)sno,sname,marks from @tbl)
select * from cte where sno=1
 
Share this answer
 
v2
Comments
Member 13867163 26-Jul-18 4:26am    
No this query producing unique records. But I want the result as below.
1 A 10
2 A 10
This should be my result
pls suggest

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900