Вопрос:
Предполагая, что у меня есть таблица 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)