2011-02-01 23 views
0

私は、属性のグループを格納しているテーブルを持っており、それらを一連の順序で並べています。属性(行)の1つが表から削除され、位置の順序が圧縮される可能性があります。例えばSQL行の塗りつぶしシーケンス

、私は本来、これらの値を設定した場合:削除された

+----+--------+-----+ 
| id | name | pos | 
+----+--------+-----+ 
| 1 | one | 1 | 
| 2 | two | 2 | 
| 3 | three | 3 | 
| 4 | four | 4 | 
+----+--------+-----+ 

2行目に、すべての後続の行の位置は、ギャップを閉じるために、更新されるべきです。

+----+--------+-----+ 
| id | name | pos | 
+----+--------+-----+ 
| 1 | one | 1 | 
| 3 | three | 2 | 
| 4 | four | 3 | 
+----+--------+-----+ 

単一のクエリでこのアップデートを行う方法があります:結果はこのすべきですか?どうすればこのことができますか?

PS:システムが両方のエンジンをサポートするはずなので、SQLServerとOracleの両方の例をお勧めします。ありがとう!

更新:この理由は、ユーザーが自由に位置を変更することができ、新しい行を追加または削除することができるからです。ポジションはユーザーに表示されます。そのため、これらは常にコンシステンスシーケンスを表示する必要があります(このシーケンスは必要に応じて保存する必要があります)。

+1

これはリソースの浪費になる可能性があります。基本的にはソートしてから、すべての行を注文番号で更新します。 300万のレコードを持ち、行1を削除するとどうなりますか? 2,999,999の更新を発行する必要があります! あなたはここで何を達成しようとしていますか?多分もっと良いものをデザインするのに役立つかもしれません。 – diagonalbatman

+0

まあ、ここにポイントがあります。しかし、テーブルには数百行以上のデータが含まれていることは想定されていないため、パフォーマンスに大きな影響はありません(このクエリはおそらく100クエリのバッチの一部です。 –

+0

ここでは並行処理は行われません。セッションBが「3」を削除すると同時にセッションAが「2」を削除すると、ロックの問題が発生します。バッチジョブの場合、それは問題ではないかもしれません。 –

答えて

4

わからない、それは動作しますが、オラクルで、私は次のようしようとするだろう:

update my_table set pos = rownum; 
+0

魅力的なように働いています:)しかし、それは行がそれらが属するシーケンスに挿入されたと仮定しています。行の順序を並べ替える順序を指定するにはどうすればよいですか?たとえば、行が4,2,1,3(およびposの等しい行ID)の順に挿入され、2行が削除された場合、このクエリは4 = 1,1 = 2,3 = 3のようなシーケンスを代入します。 4 = 3,1 = 1,3 = 2である。 –

+0

Oracleで単純ビューを更新できます。おそらく、 'update(select * from my_table order by id)' set pos = rownum'を使用してください。 – Benoit

+0

Damn。有望に見えたが、うまくいかなかった。 ORA-01732 - "このビューではデータ操作操作が正しくありません"。 : –

0

これは動作しますが、大規模なデータセットのための次善のことがあります

SQL> UPDATE my_table t 
    2  SET pos = (SELECT COUNT(*) FROM my_table WHERE id <= t.id); 

3 rows updated 

SQL> select * from my_table; 

     ID NAME    POS 
---------- ---------- ---------- 
     1 one     1 
     3 three    2 
     4 four    3 
0

あなたが本当にシーケンス値が必要です連続しているか、連続した値を表示できるだけでいいですか?

select id, 
     name, 
     dense_rank() over (order by pos) as pos, 
     pos as sparse_pos 
from my_table 

(注意:これはOracle固有のクエリである)

をあなたがポジションを作る場合は、これを行うための最も簡単な方法は、実際の配列が疎になってみましょうと秩序を基調とするランクを計算することです。最初の場所ではまばらなので、2つの既存の位置の中間に新しい位置を作ることができるので、これにより並べ替えが容易になります。たとえば、あなたがこのようなテーブルを持っていた場合:それはポジション2にID 4を移動する時間になると

+----+--------+-----+ 
| id | name | pos | 
+----+--------+-----+ 
| 1 | one | 100 | 
| 2 | two | 200 | 
| 3 | three | 300 | 
| 4 | four | 400 | 
+----+--------+-----+ 

して、あなただけの150


さらなる説明に位置を変更したいです: (あなたが位置をマスキングしているため)上記の例を使用

、ユーザーが最初に次のことを見ている:

+----+--------+-----+ 
| id | name | pos | 
+----+--------+-----+ 
| 1 | one | 1 | 
| 2 | two | 2 | 
| 3 | three | 3 | 
| 4 | four | 4 | 
+----+--------+-----+ 

ユーザーは、インターフェースを介してポジション4のレコードをポジション2に移動する必要があることを示すと、ID 4の位置を150に更新してから、クエリーを再実行します。ユーザーには次のように表示されます。

+----+--------+-----+ 
| id | name | pos | 
+----+--------+-----+ 
| 1 | one | 1 | 
| 4 | four | 2 | 
| 2 | two | 3 | 
| 3 | three | 4 | 
+----+--------+-----+ 

これがうまくいかない理由は、ユーザーがデータベースで直接データを編集している場合だけです。その場合でも、私はビューとトリガーの代わりに、この種のソリューションを使用する傾向があります。

+0

残念ながら、ユーザーはポジションを操作することができますので、実際のシーケンスをデータベースに保存する必要があります。 –

関連する問題