1

一連のペグを1つのボックスに結び付けるBoxPegというリンクテーブルがあります。

欠点は、ペグが順序付けられ、クライアントソフトウェアで配列として扱われることです。

したがって、BoxPegテーブルに「position」というINTUNSIGNED列があります。

誰かがボックスにペグを追加するたびに、これを行います。

UPDATE BoxPeg SET position = position+1 WHERE box = '{BOXID}' AND position >= {NEWPEGPOSITION};
INSERT INTO BoxPeg(box, peg, position) VALUES('{BOXID}', '{PEGID}', {NEWPEGPOSITION});

これは、クライアントが大きすぎる新しいペグ位置をなんとか通過するまで正常に機能します。

before:
0
1
2
3

after insert 9
0
1
2
3
9

これらの2行の前の別のSQLステートメントでMAX(position)WHERE box ='{BOXID}'を取得し、それに基づいて新しいペグ位置を調整できることはわかっていますが、シリーズ全体を単純にリフローしたいと思います。インサート後のワンショット。このようにして、シリーズの最初から最後までどこにもギャップがないことを100%確信しています。

そのUPDATEはどのようになりますか?

この状況を考えてみましょう。

before:
0
2
5
8

after insert 5
0
2
5
6
9

after reflow
0
1
2
3
4
4

1 に答える 1

0

次のように行をリフローできます。

UPDATE BoxPeg bp
INNER JOIN (
  SELECT *, @n := @n + 1 AS newpos
  FROM BoxPeg, (SELECT @n := -1) x
  WHERE box = '{BOXID}'
  ORDER BY position
) s
 ON bp.box = s.box
AND bp.peg = s.peg
SET bp.position = s.newpos
WHERE bp.position <> s.newpos
;

副選択は、変数を使用してposition、特定のによって定義されたサブセットの新しい値を計算します{BOXID}。次に、UPDATEステートメントは副選択を結合しBoxPeg、一致する行を新しい値で更新します。(したがって、に結合されるBoxPegと、副選択はフィルターとしても機能し、更新された行を特定のボックスに属する行に制限します。)

このクエリのSQLFiddleデモが利用可能です

position列が一意性制約の一部である場合、このメソッドが常に機能するとは限らないことに注意してください。このクエリが生成する新しい値は一意ですが、MySQLは、ステートメントの実行の最後ではなく、更新中に一意の制約を評価するようです。したがって、行が更新される順序によっては、行がまだ更新されていない別の行の値と同じ値を受け取っている場合、クエリが失敗する可能性があります。

于 2013-02-18T07:20:21.823 に答える