Member 13867163 Ответов: 2

Выбрать повторяющиеся записи


Привет,

У меня есть запрос ниже

declare @tbl table (id int identity(1,1),sname varchar(10),marks int)
вставить @ТБЛ значений('а',10),('Б',10),('А',10),('Б',40),('С',10),('Д',15), ("а", 9)
выберите функции row_number()над(раздел по sname,порядок знаков знаки)СНО,sname,следы от @ТБЛ

мой результат таков:
sno sname marks
1 а 9
1 А 10
2 А 10
1 B 10
1 B 40
1 с 10
1 D 15

Но я хочу только вторую и третью строки, так как это дубликаты записей. мне нужны все дубликаты записей, независимо от повторения.

Пожалуйста предложите

Спасибо

Что я уже пробовал:

устранение дубликатов записей

2 Ответов

Рейтинг:
2

Member 11621026

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


Member 13867163

Нет этого запроса, производящего уникальные записи. Но я хочу получить результат, как показано ниже.
1 А 10
2 А 10
Это должно быть моим результатом
пожалуйста предложите

Рейтинг:
1

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


Member 13867163

Если я возьму Sno=1, то получу уникальные записи, игнорирующие дубликаты

Если я возьму Sno>1, то я получу записи, которые имеют дубликаты (в этом случае A придет, потому что у него есть дубликаты)

Но что нужно, так это то, что я хочу получить имя с тем, сколько раз оно повторяется, как показано ниже.
Sno Sname Marks
1 А 10
2 А 10
остальные записи не нужны.

CHill60

Ах... так вы только хотите посмотреть записи, которые иметь дубликаты, а сколько их было? Дай мне несколько минут.

CHill60

Извините за это - я обновил свое решение

Member 13867163

Отличный..
Спасибо
это прекрасно работает

CHill60

Отлично - вы можете "принять" решение, если хотите - это указывает другим посетителям, что это было то, что сработало (вместо того, чтобы им приходилось читать комментарии)

Member 13867163

это работает нормально, но есть ли какое-либо другое решение для вышеизложенного.
потому что если это два столбца, то нет проблем, многие столбцы занимают много времени для условий on..

CHill60

Мы могли бы что-нибудь сделать с этим. КОНТРОЛЬНАЯ СУММА[^] по всем затронутым столбцам ... Но я не могу вернуться к этому некоторое время

CHill60

Я обновил свое решение с помощью альтернативного подхода