36

データベースにオブジェクトのコレクションがあります。フォトギャラリーの画像、カタログの製品、本の章など。各オブジェクトは行として表されます。これらの画像を任意に並べ替えてデータベースに保存し、オブジェクトを表示するときに正しい順序になるようにしたいと思います。

たとえば、私が本を書いていて、各章がオブジェクトであるとします。私は自分の本を書き、章を次の順序で並べます。

はじめに、アクセシビリティ、形態と機能、エラー、一貫性、結論、索引

それはエディターに送られ、次の推奨される順序で返されます。

はじめに、フォーム、機能、アクセシビリティ、一貫性、エラー、結論、インデックス

この順序を堅牢で効率的な方法でデータベースに保存するにはどうすればよいですか?

私は次のアイデアを持っていますが、それらのどれにもわくわくしていません。

  1. 配列。各行には注文IDがあり、注文が変更されると(削除とその後の挿入によって)、注文IDが更新されます。これにより、検索が簡単になりますORDER BYが、壊れやすいようです。

    // REMOVAL
    UPDATE ... SET orderingID=NULL WHERE orderingID=removedID
    UPDATE ... SET orderingID=orderingID-1 WHERE orderingID > removedID
    // INSERTION
    UPDATE ... SET orderingID=orderingID+1 WHERE orderingID > insertionID
    UPDATE ... SET orderID=insertionID WHERE ID=addedID

  2. リンクリスト。各行には、順序付けの次の行のIDの列があります。ORDER BYここではトラバーサルにコストがかかるようですが、私が考えていない方法で使用できる場合があります。

  3. スペース配列。orderingID(#1で使用)を大きく設定して、最初のオブジェクトが100、2番目のオブジェクトが200などになるようにします。次に、挿入が発生したら、それをに配置し(objectBefore + objectAfter)/2ます。もちろん、これは時々リバランスする必要があるので、物事が近すぎないようにします(フロートを使用しても、最終的に丸め誤差が発生します)。

これらのどれも私には特にエレガントに見えません。誰かがそれを行うためのより良い方法を持っていますか?

4

11 に答える 11

7

もう 1 つの方法は、(RDBMS がサポートしている場合) 配列型の列を使用することです。これは正規化のルールに違反しますが、このような状況では役立ちます。私が知っている配列を持つデータベースの 1 つに PostgreSQL があります。

于 2008-08-22T05:32:46.497 に答える
4

Railsのacts_as_listミックスインは、基本的に#1で概説した方法でこれを処理します。これは、position(もちろん名前にオーバーライドできます)と呼ばれるINTEGER列を探し、それを使用してORDERBYを実行します。物を並べ替えたいときは、位置を更新します。それは私がそれを使うたびに私にうまく役立ってきました。

補足として、スパースな番号付けを使用することで、INSERTS / DELETESで常に再配置を行う必要をなくすことができます。これは、当時の基本的なもののようなものです...位置に10、20、30などの番号を付けることができます。また、10から20の間に何かを挿入する必要がある場合は、15の位置で挿入するだけです。同様に、削除するときは、行を削除してギャップを残すことができます。実際に順序を変更する場合、または挿入を実行しようとして挿入する適切なギャップがない場合にのみ、番号の付け直しを行う必要があります。

もちろん、特定の状況(たとえば、他の行がすでにメモリにロードされているかどうか)に応じて、ギャップアプローチを使用することが理にかなっている場合とそうでない場合があります。

于 2008-08-21T23:11:17.820 に答える
3

オブジェクトが他のテーブルによって強くキー設定されておらず、リストが短い場合は、ドメイン内のすべてを削除して、正しいリストを再挿入するのが最も簡単です。ただし、リストが大きく、削除を遅くするための制約がたくさんある場合は、これは実用的ではありません。私はあなたの最初の方法が本当に最もきれいだと思います。トランザクションで実行する場合は、更新の途中で注文を台無しにする間、何も奇妙なことが起こらないことを確認できます。

于 2008-08-22T01:39:15.390 に答える
3

オプション#1と#3を検討するだけです。間隔を空けた配列オプション(#3)は、通常の配列(#1)の問題を延期するだけではありませんか?どのアルゴリズムを選択しても、アルゴリズムが壊れていて、後で#3で問題が発生するか、または機能し、#1も同様に機能するはずです。

于 2008-08-25T17:24:13.627 に答える
2

私は前回のプロジェクトでこれを行いましたが、特別に注文する必要があるのはたまにしかなく、あまり頻繁にアクセスされなかったテーブル用でした。間隔を空けた配列が最良のオプションだと思います。これは、1つの値への変更と、2つの値へのクエリを含むだけで、平均的な場合に並べ替えが最も安価になるためです。

また、ORDER BYはデータベースベンダーによってかなり大幅に最適化されると思います。そのため、この関数を利用すると、リンクリストの実装とは対照的にパフォーマンスが向上します。

于 2008-08-22T01:58:14.423 に答える
2

浮動小数点数を使用して、各アイテムの位置を表します。

項目 1 -> 0.0

項目 2 -> 1.0

項目 3 -> 2.0

項目 4 -> 3.0

単純な二等分によって、任意のアイテムを他の 2 つのアイテムの間に配置できます。

項目 1 -> 0.0

項目 4 -> 0.5

項目 2 -> 1.0

項目 3 -> 2.0

(項目 4 を項目 1 と 2 の間に移動)。

コンピュータ システムでの浮動小数点数のエンコード方法により、二分プロセスはほぼ無期限に続行できます。

項目 4 -> 0.5

項目 1 -> 0.75

項目 2 -> 1.0

項目 3 -> 2.0

(項目1を項目4の直後に移動)

于 2008-09-18T00:22:32.820 に答える
2

私は主に Django でこれに遭遇したので、この解決策が最も実行可能であることがわかりました。リレーショナル データベースでこれを行う「正しい方法」はないようです。

于 2009-03-29T14:47:15.043 に答える
1

優先順位がすでに存在する場合は、優先順位の「スペースを空ける」トリガーをテーブルに付けて、連続番号を実行します。

于 2008-08-21T23:12:30.123 に答える
1

私もこの問題を抱えていました。私は大きな時間的プレッシャーにさらされていました (私たち全員ではありません)、オプション #1 を使用し、変更された行のみを更新しました。

アイテム 1 をアイテム 10 と交換する場合、アイテム 1 とアイテム 10 の注文番号を更新するために 2 つの更新を行うだけです。アルゴリズム的に単純であり、O(n) の最悪のケースであることはわかっていますが、その最悪のケースは、リストの完全な順列。それはどのくらいの頻度で起こりますか?それはあなたが答えてください。

于 2008-09-18T00:34:31.777 に答える
0

私は同じ問題を抱えており、おそらく少なくとも 1 週間は適切なデータ モデリングについて考えていましたが、ようやく理解できたと思います。PostgreSQL で配列データ型を使用すると、注文された各アイテムの主キーを格納し、注文が変更されたときに挿入または削除を使用してその配列を適宜更新できます。単一の行を参照すると、配列列の順序に基づいてすべてのオブジェクトをマップできます。

これはまだ少し途切れ途切れのソリューションですが、オプション 1 では順序変更時に他のすべての行の順序番号を更新する必要があるため、オプション 1 よりもうまく機能する可能性があります。

于 2016-01-28T10:32:16.580 に答える