2009-08-23 11 views
4

webappの各ユーザーには、n関連のウィジェットがあります。各ウィジェットはウィジェットテーブルのデータベースに表示されます。ユーザーはウィジェットを並べ替えることができます。数十ものウィジェットを持つことは決してなく、頻繁にウィジェットを並べ替えます。ユーザーソート可能なレコード

私は非常に頻繁に固有の順序を持​​つデータベース項目を扱っていません。注文のための良い戦略は何ですか?最初は、単純な "sortIndex"カラムはうまくいくと思いましたが、この値を初期化する方法が不思議でした。おそらく、一意の値でなければならず、他のすべてのソートインデックスよりも大きくても少なくてもかまいません。私は新しいウィジェットを作成するたびに、そのユーザーの他のソートインデックスをすべてチェックする必要はありません。それは不要です。

おそらく、デフォルトの「ボトム優先」ソートインデックスを持つことができますか?しかし、どのようにそれらを区別するのですか?私は、作成日フラグを使用することができると思うが、その場合、ユーザがそれらの優先順位の低いウィジェットのすべての中にウィジェットを挿入したい場合はどうなるだろうか?

このようなことを処理する標準的な方法は何ですか?

答えて

3

ユーザーが編集可能なソートのための最善の方法は、linked listid年代を維持することです:

user_id widget_id prev_widget_id 
    ----  ----   ---- 
     1   1    0 
     1   2    8 
     1   3    7 
     1   7    1 
     1   8    3 
     2   3    0 
     2   2    3 

これは、この順でuser 1ため5ウィジェットを行います。1, 7, 3, 8, 2。そして、この順でuser 2ため2ウィジェット:3, 2

あなたは(user_id, widget_id)(user_id, prev_widget_id)UNIQUEインデックスを作成する必要があります。

意図順にウィジェットを取得するには、Oracleで、たとえば、次のように照会できます。

SELECT w.* 
FROM (
     SELECT widget_id, level AS widget_order 
     FROM widget_orders 
     START WITH 
       user_id = :myuser 
       AND prev_widget_id = 0 
     CONNECT BY 
       user_id = PRIOR user_id 
       AND prev_widget_id = PRIOR widget_id 
     ) o 
JOIN widgets w 
ON  w.widget_id = o.widget_id 
ORDER BY 
     widget_order 

が注文を更新するには、あなたが最も3行で更新する必要があります(あなたが全体を移動する場合でも、ウィジェットのブロック)。

SQL ServerPostgreSQL 8.4再帰CTE Sを使用してこの機能を実装:

WITH  
-- RECURSIVE 
-- uncomment the previous line in PostgreSQL 
     q AS 
     (
     SELECT widget_id, prev_widget_id, 1 AS widget_order 
     FROM widget_orders 
     WHERE user_id = @user_id 
     UNION ALL 
     SELECT wo.widget_id, wo.prev_widget_id, q.widget_order + 1 
     FROM q 
     JOIN wo.widget_orders wo 
     ON  wo.user_id = @user_id 
       AND wo.prev_widget_id = q.widget_id 
     ) 
SELECT w.* 
FROM q 
JOIN widgets w 
ON  w.widget_id = q.widget_id 
ORDER BY 
     widget_order 

MySQLでこの機能を実装する方法についての私のブログでこの記事を参照してください。

4

あなたは自分の個人的な好みのためのウィジェットを並べ替えユーザーがいる場合、あなたはそのように、ルックアップテーブルを作成したい:

select 
    w.* 
from 
    widgets w 
    inner join widgets_sorting s on 
     w.WidgetID = s.WidgetID 
    inner join users u on 
     s.UserID = u.UserID 
order by 
    s.SortIndex asc 

これを:

create table widgets_sorting 
(
    SortID int primary key, 
    UserID int, 
    WidgetID int, 
    SortIndex int 
) 

その後、ユーザーのウィジェットをソートします新しいユーザーのために行う必要があるのは、widgets_sortingテーブルに新しい行を追加することだけです。外部キー制約とインデックスをWidgetID列とUserID列の両方に配置してください。

これらのルックアップテーブルは、このようなパーソナライズされたリスティングに共通する多対多リレーションシップを解決する最も良い方法です。うまくいけば、これはあなたを正しい方向に向けるでしょう!

1

私は2テーブルアプローチを使いたいですが、ちょっと混乱するかもしれませんが、ActiveRecordなどのORMを使用していれば簡単ですし、ちょっとしたコードを書けば管理が容易です。

1つの表を使用してユーザーをソートにリンクし、1つの表を使用してウィジェットと位置およびソートをリンクします。こうすることで、何が起こっているのかがはっきり分かり、SQL結合や別のクエリを使用して、さまざまなテーブルからさまざまなデータを取り出すことができます。あなたの構造は次のようになります。

//Standard user + widgets table, make sure they both have unique IDs 
CREATE TABLE users; 
CREATE TABLE widgets; 

//The sorting tables 
CREATE TABLE sortings (
    id INT, //autoincrement etc, 
    user_id INT 
) 

CREATE TABLE sorting_positions (
    sorting_id INT, 
    widget_id INT, 
    position INT 
) 

うまくいけば、これはあなたがまだ混乱している場合、理にかなっています。このメッセージにコメントし、私はいくつかの基本的なコードをあなたを書きます。

ジェイミー

1

各ユーザーがウィジェットに自分のソート順を割り当てることを意味している場合、エリックの答えは正しいです。おそらくあなたはソート値を割り当てる方法をユーザに与えなければならないだろう。しかし、あなたが言うように数字が控えめであれば、すべてのウィジェットをリストした画面を与えて、注文番号で入力させるか、順番に表示して、それぞれの横に上下のボタンを置くことができます彼にドラッグアンドドロップする方法を与えるファンシーになりたい。

すべてのユーザーの注文が同じ場合、この注文はどこから来たのですか?それが恣意的な場合は、新しいウィジェットが作成されるたびにシーケンス番号を割り当てます。

関連する問題