Как сравнить несколько строк одной и той же таблицы SQL

Вопрос:Предполагая, что у меня есть таблица SQL Server, которая выглядит так: id valA valB valC ----------------------- 1 1 2 3 2 4 5 6 3 7 8 9 3 10 11 12 4 13 14 15 4 16 14 15 Я хочу сравнить строки, чтобы найти те, которые имеют определенное соответствие данных. В этом случае

Вопрос:

Предполагая, что у меня есть таблица SQL Server, которая выглядит так:

id valA valB valC ———————— 1 1 2 3 2 4 5 6 3 7 8 9 3 10 11 12 4 13 14 15 4 16 14 15

Я хочу сравнить строки, чтобы найти те, которые имеют определенное соответствие данных. В этом случае я хочу идентифицировать строки с совпадающими идентификаторами, valB и valC, поэтому он должен найти только последние две строки. Содержимое столбца valA игнорируется.

Затем я хочу удалить одну из двух строк, а затем отрегулирую столбцы valA по мере необходимости. Моя проблема заключается в определении совпадающих строк.

Из многих других подобных вопросов на этом сайте я пробовал разные вещи, похожие на это:

SELECT DISTINCT A.id FROM newtable A INNER JOIN newtable B ON A.id = B.id WHERE A.valB = B.valB AND A.valC = B.valC

но я получаю все четыре идентификатора. Я не знаю, почему. Даже если это сработало, я все еще не уверен, как приступить к обновлению и удалению действий, необходимых для поиска всех найденных совпадающих строк. Какие-либо предложения? Спасибо.

Ответ №1

Я думаю, вы близки. Вам просто нужно исключить строки, которые вы не хотите:

SELECT DISTINCT A.id FROM newtable A INNER JOIN newtable B ON A.id = B.id WHERE A.valB = B.valB AND A.valC = B.valC AND A.valA <> B.valA; Ответ №2

Вы также можете использовать HASHBYTES. Если у вас есть эти типы запросов, то много индексирования столбца HASHBYTES поможет в сравнении.

ДЕМО ЗДЕСЬ

create table #temp ( id int, vala int, valb int, valc int ) insert into #temp select 1,2,3,4 union all select 4,8,10,12 union all select 1,5,3,4 ;With cte as ( select *, dense_rank() over ( order by (HASHBYTES(‘SHA2_512’,CONCAT(id,valb,valc)))) as rownum from #temp ) select * from cte where rownum>1

или вы можете просто использовать DenseRank..

;With cte as ( select *, dense_rank() over ( order by id,valb,valc) as rownum from #temp ) select * from cte where rownum>1 Ответ №3

… Моя проблема заключается в идентификации совпадающих строк.

Чтобы выбрать соответствующие строки, используйте это:

;with x as ( select *, count(*) over (partition by id, valb, valc) as N from YourTable ) — matching values select x.id, x.vala, x.valb, x.valc from x where x.N > 1

… Я все еще не уверен, как продолжить обновление и удаление действий…

— deleting from YourTable where id, valb and val c are repeated and vala != valb — 1 delete from x where x.N > 1 and x.vala != x.valb -1

Я советую сделать выбор раньше, чтобы увидеть, что будет удалено.

Выбор скрипта: http://sqlfiddle.com/#!6/ae27b/5

Fiddle delete from: http://sqlfiddle.com/#!6/ae27b/2

Включить ROW_NUMBER из записи в исходной таблице (упорядочен по идентификатору): http://sqlfiddle.com/#!6/ae27b/14

Ответ №4

Если вам нужен только идентификатор, для которого есть по крайней мере две строки с одинаковыми значениями valb и valc, вы можете использовать это:

select distinct id from t group by id, valb, valc having count(*) > 1;

Если вам нужно получить и другие столбцы, вы можете использовать функцию окна count следующим образом:

select * from ( select t.*, count(*) over (partition by id, valb, valc) cnt from t ) t where cnt > 1; Ответ №5

сообщите свое требование больше, например, какой параметр вы передадите и т.д.

вы можете попробовать это,

declare @t table(id int,valA int,valB int,valC int) insert into @t values (1 , 1 , 2 , 3 ) ,(2 , 4 , 5 , 6 ) ,(3 , 7 , 8 , 9 ) ,(3 , 10 , 11 , 12) ,(4 , 13 , 14 , 15) ,(4 , 16 , 14 , 15) ;With CTE as ( select * ,row_number()over(partition by id,valb,valc order by id)rn from @t ) ,CTE1 as ( select * from cte where rn>1 ) select * from @t t where EXISTS( select id from cte1 c where t.id=c.id)

Оцените статью
Добавить комментарий