CHill60
Если sno
всегда будет 1 (потому что вы разделяете на sname
И marks
) вы могли бы упростить это до
select distinct 1 as sno,sname, marks from @tbl
Ключевым моментом является то, что именно ваше введение row_number() на самом деле вызывает проблему.
Но я подозреваю, что вы хотите
sno
быть чем-то значимым (поправьте меня, если я ошибаюсь)
Если вы хотите, чтобы он показывал номер метки на имя, то используйте
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
что даст вам
sno sname mark
1 A 9
2 A 10
1 B 10
2 B 40
1 C 10
1 D 15
Если вы хотите присвоить каждой строке номер, то удалите раздел полностью
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
------------------ РЕДАКТИРОВАТЬ ПОСЛЕ КОММЕНТАРИЯ OP ---------------
Чтобы получить только те строки, которые дублируются, вы можете попробовать два способа:
1. Чтобы получить sname и метки, а также количество дубликатов, попробуйте сделать это
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. Чтобы получить полный список элементов, имеющих дубликаты, попробуйте сделать это:
;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
Ключ-это внутреннее соединение на подзапросе, который смотрит на CTE во второй раз. Это не просто "дайте мне строки, где sno > 1" - соединение гарантирует, что пока мы не видим неповторяющихся строк, мы
делать видеть
все строки, где был дубликат - то есть 10, где sno - 1 и 2, а не только 2
----------------- РЕДАКТИРОВАТЬ ПОСЛЕ ОП ЕЩЕ ОДИН КОММЕНТАРИЙ ---------------
Вводя другие столбцы, которые должны быть приняты во внимание - соединения занимают "много времени для условий on
Тестовые данные:
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)
Мое первоначальное решение вернется
1 A 10 2 3
2 A 10 1 3
3 A 10 1 3
Что неверно при учете
other
колонка.
Мы можем использовать
Контрольная сумма [
^] чтобы "объединить" все релевантные столбцы, например
;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
результаты
A 10 1
A 10 1