2017-01-05 8 views
0

私は一意のIDフィールドの重複を強調表示し、重複としてv2、v3を追加する必要があるplsqlパッケージを持っています。一意のID 111は、111回、111回、111回2回、111回3回発生します。重複と増分値の検索

マイコードアレックスプールに述べたように、それぞれが同一の、例えばようV2 111 V2 111 111 V2

PROCEDURE find_duplicates IS 
     c_amt   INT; 
     c_id   VARCHAR2(255); 
     c_id_new  VARCHAR2(255); 
     v_count   int; 

     cursor c_duplicates is 
     select UNIQUE_ID,Qty from (
      select UNIQUE_ID, count(*) as Qty from dbo.Temp_Weekly_Export_File 
      group by UNIQUE_ID 
      having count(*) > 1) where Qty >1; 
    BEGIN 
     BEGIN 
      v_count := 0; 

      open c_duplicates; 
      LOOP 
      FETCH c_duplicates into c_id, c_amt; 
      v_count := v_count + 1; 
      c_id_new := c_id||'_V'||v_count; 

      --DBMS_OUTPUT.PUT_LINE('C_ID: '||c_id); 
      UPDATE dbo.Temp_Weekly_Export_File 
      SET UNIQUE_ID=c_id_new 
      where unique_id=c_id; 

      EXIT WHEN c_duplicates%NOTFOUND; 
      END LOOP; 
     END; 
    END; 
+0

これはすべて同じではありません。 3行すべてを3回更新しています。あなたのアップデートのフィルタを見てください - 毎回、IDと一致するループ*すべての*行が更新されます。実際には、いいえ、それは各IDのために1回だけループを回ります - それらはすべて111_v1として終わるべきですか?とにかく...変更されたIDもまだ存在しないのですか? –

+0

ありがとうアレックス、これはSQLのdoableあなたは知っていますか?私はPLSQLにはとても慣れていません。はい、変更されたIDは存在しませんので、単にインクリメントするv2、v3などに追加するだけです。 –

答えて

3

あなたは、その列でグループ化しているので、あなたのコードは一度だけ各unqiue_idを見ているをテストしていません。複数の行を持つIDごとに、すべてのIDが同じV番号に更新されます。また、IDごとにv_countをリセットしないため、重複している最初のIDの行はすべてV1に更新されます。重複した2番目のIDはすべてV2に設定されます。

これはマージで行うことができます。目標は、各列のIDと行IDを取得するクエリであり、ソースは、これらに加えて、各IDの数と(分析関数を介して)それぞれの各発生の任意のランキングを取得します

create table Temp_Weekly_Export_File (unique_id varchar2(10)); 
insert into Temp_Weekly_Export_File values ('111'); 
insert into Temp_Weekly_Export_File values ('111'); 
insert into Temp_Weekly_Export_File values ('111'); 
insert into Temp_Weekly_Export_File values ('112'); 
insert into Temp_Weekly_Export_File values ('112'); 
insert into Temp_Weekly_Export_File values ('113'); 

merge into 
(
    select unique_id, rowid 
    from Temp_Weekly_Export_File 
) t 
using (
    select unique_id, 
    row_number() over (partition by unique_id order by 1) as rnk, 
    count(*) over (partition by unique_id) as cnt 
    from Temp_Weekly_Export_File 
) s 
on (s.rowid = t.rowid and s.cnt > 1) 
when matched then 
update set t.unique_id = s.unique_id ||'_V'||s.rnk; 

3 rows merged. 

select * from Temp_Weekly_Export_File; 

UNIQUE_ID 
---------- 
111_V1 
111_V2 
111_V3 
112V_1 
112V_2 
113 

on句は、マージ自体によって更新されない列を使用しなければならないので、単にunique_idを使用することはできません。 rowidはここで十分に安定しているはずです。

V1、V2などの行を決定することができる/できない列がある場合は、おそらくタイムスタンプですか? - 私が使用したダミー定数の代わりにそれを使って注文することができます。これはインクリメントされたV値を不定期に割り当てます。

質問にあるように、テーブル名の前に接頭語「dbo.」が必要な場合もあります。これを手続きで行う必要がある場合は、MTOが言ったようにラップしてください:

PROCEDURE find_duplicates IS 
BEGIN 
    merge into 
    (
    select unique_id, rowid 
    from dbo.Temp_Weekly_Export_File 
) t 
    using (
    select unique_id, 
     row_number() over (partition by unique_id order by 1) as rnk, 
     count(*) over (partition by unique_id) as cnt 
    from dbo.Temp_Weekly_Export_File 
) s 
    on (s.rowid = t.rowid and s.cnt > 1) 
    when matched then 
    update set t.unique_id = s.unique_id ||'_V'||s.rnk; 
END find_duplicates; 
+0

ありがとう、マージのために、私は無効なテーブル名を述べているエラーを取得しています。私はマージを使用したことがないので、単にそのセクションを実行するか、他に何かをしなければなりませんか? –

+1

あなたはそのセクションを実行するだけです(必要であれば手続きでラップできますが、必要ではありません)。ああ...私はローカルテーブルを作成しました。あなたがそのユーザーとしてこれを実行していない場合は、両方の 'from'節であなたの前に' dbo.'を付ける必要があります。 –

+1

プロシージャにコードを置くために必要な場合は、merge文を 'PROCEDURE find_duplicates IS BEGIN'と' END; 'で囲むだけですが、Alexが言ったように、merge文を直接実行することができます。 (カーソルを使用する必要もありません) – MT0

2

を設定重複が、扱いを強調表示条件を区別しない場合ので、それは、3つのすべての行を更新してしたがって、rowidを使用して複製を検索し、同じものを更新することができます。

PROCEDURE find_duplicates 
    IS 

     cursor c_duplicates is 
     select UNIQUE_ID,rnk,rdfrom (
      select UNIQUE_ID 
       ,rowid rd 
       ,DENSE_RANK() OVER(PARTITION BY UNIQUE_ID ORDER BY rowid asc) rnk 
       ,COUNT(*) OVER(PARTITION BY UNIQUE_ID) cnt    from dbo.Temp_Weekly_Export_File 
      ) where cnt>1; 
    c_duplicates_rec c_duplicates%ROWTYPE;  
    BEGIN 
     open c_duplicates; 
      LOOP 
      FETCH c_duplicates into c_duplicates_rec; 
      EXIT WHEN c_duplicates%NOTFOUND; 

      UPDATE dbo.Temp_Weekly_Export_File 
      SET UNIQUE_ID=c_duplicates_rec.UNIQUE_ID||'_V'||c_duplicates_rec.rnk 
      where rowid=c_duplicates_rec.rd; 
      END LOOP; 
      CLOSE c_duplicates; 
    EXCEPTION 
    WHEN OTHERS THEN 
    IF c_duplicates%ISOPEN THEN CLOSE c_duplicates; END IF; 
    RAISE; 
    END; 

PS:私は、コード

+0

上記のコードでは、重複の最初のレコードも111v1に更新されます。あなたの要件 –

関連する問題