2017-02-05 5 views
3

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

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 

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

+0

какой параметр вы пройдете? – KumarHarsh

ответ

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; 
+0

Спасибо, теперь я понимаю, почему все строки появились, потому что они находили совпадение между данной строкой и той же строкой в ​​другой (той же) таблице. Проблема с добавлением того, что у вас есть, это то, что содержимое valA может иногда совпадать. Я думаю, что могу исправить это, имея уникальное поле id в таблице. – AngeloQ

+0

@AngeloQ. , , Да, уникальный идентификатор решит проблему, которую я пытаюсь решить с помощью сравнения на 'valA'. –

1

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

DEMO HERE

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 
+0

Спасибо, хорошие идеи. MSSQL жаловался на CONCAT в первом примере. Второй пример выполнялся, но вывел всю таблицу, просто упорядочен по id. – AngeloQ

+0

concat works from sql2008 – TheGameiswar

+0

OK спасибо, используя SQL Server 2005. – AngeloQ

0

Если вам просто нужно идентификатор, для которого существует зарегистрировано не менее двух строк с таким же 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; 
+0

Первый пример с группой - хорошая идея, если SELECT содержит столбцы, которые находятся в GROUP BY, иначе это дает мне ошибку. Возможно, я смогу работать с этим. Второй пример не работал для меня, возможно, синтаксическая ошибка? Я попытался исправить это, но не смог. – AngeloQ

1

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

Для выбора подходящих строк используйте:

;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 

Советую сделать выбор перед тем, чтобы увидеть, что будет удалено.


Fiddle выберите матчи: http://sqlfiddle.com/#!6/ae27b/5

Fiddle удалить из: http://sqlfiddle.com/#!6/ae27b/2

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

+0

Спасибо, это работает лучше всего для меня. Я получаю эту ошибку от MSSQL Server 2005, хотя: «Конструкция или оператор OVER SQL не поддерживается». Но он все еще работает и, кажется, дает ожидаемые результаты. – AngeloQ

+0

Также, как я могу получить номер строки, или каким другим способом было бы проще вернуться к этой строке в исходной таблице. Я на самом деле вижу, что я не могу просто удалить вторую строку, пока я не объединю их вместе. Мне нужно проверить содержимое valA (и других столбцов) и скопировать значения перед удалением второй строки. – AngeloQ

+0

@AngeloQ, что-то вроде этого? http://sqlfiddle.com/#!6/ae27b/14 –

0

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

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

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)