2017-02-05 16 views
3

私はこのようになりますSQL Serverのテーブルを持っていると仮定すると:同じ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 

私は特定のデータマッチングを有するものを見つけるために、行を比較したいです。この場合、id、valB、valCが一致する行を識別したいので、最後の2行だけを見つけます。 valA列の内容は無視されます。

次に、2行のうちの1行を削除して、必要に応じて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 

を私はすべての4つのIDを取得してしまいます。なぜ私は分からない。それがうまくいっても、見つかったすべての一致する行を取る必要がある更新と削除の処理を続行する方法がまだわかりません。助言がありますか?ありがとう。

+0

、これを試すことができますか? – KumarHarsh

答えて

1

あなたは近くにいると思います。 行を除外するために、あなたはちょうどあなたがしたくない必要があります:あなたはたくさんインデックスHASHBYTES列は比較に役立つクエリのこれらの種類を持っている.IF

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。 – AngeloQ

+0

。 。はい、一意のIDは私が 'valA'の比較で解決しようとしている問題を解決します。 –

1

ます。また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 

DEMO HERE

またはあなただけ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について不平を言った。 2番目の例は実行されましたが、idによって順序付けられたテーブル全体が生成されました。 – AngeloQ

+0

concat works from sql2008 – TheGameiswar

+0

ありがとう、SQL Server 2005を使用しています。 – AngeloQ

0

あなただけの同じvalbとVALCとの少なくとも2つの行が存在しているため、IDが必要な場合は、この使用することができます:あなたは同様に他の列を取得する必要がある場合は、

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

を私のトラブルが一致する行を識別している...

select 
    * 
from (
    select 
     t.*, 
     count(*) over (partition by id, valb, valc) cnt 
    from t 
) t where cnt > 1; 
+0

GROUP BYの列がSELECTに含まれていれば、グループの最初の例が良い考えです。そうでないとエラーが表示されます。私はそれで作業することができるかもしれません。 2番目の例は私のためには機能しませんでした。おそらく構文エラーでしょうか?私はそれを修正しようとしましたが、できませんでした。 – AngeloQ

1

:あなたはこのようにウィンドウ関数countを使用することができます。

一致する行がこの使用を選択するには:

;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

フィドルから削除:http://sqlfiddle.com/#!6/ae27b/2

(Idで注文した)元のテーブル内のレコードのROW_NUMBERを含める:http://sqlfiddle.com/#!6/ae27b/14

+0

ありがとう、これは私のために最適なようです。私はMSSQL Server 2005からこのエラーを受けています: "オーバーSQLの構文や文はサポートされていません。"しかし、それはまだ実行され、期待される結果を与えるようです。 – AngeloQ

+0

また、行番号を取得する方法、または元のテーブルのその行に戻すのが他の方法で最も簡単な方法はありますか。実際には、2つの行を最初にマージするまで、2番目の行を単に削除することはできません。私はvalA(と他の列)の内容をチェックし、2番目の行を削除する前に値をコピーする必要があります。 – 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) 
関連する問題