私は次のことをする最良の方法を考えています:
データベースに保存されているタスクのリストがあります。タスクには優先度が割り当てられています。タスクの優先度を変更して、実行する順序を並べ替えることができます。
Pivotal Trackerに非常によく似たものを考えています。
次のように想像してください。
1 Task A
2 Task B
3 Task C
4 Task D
5 Task E
Eが最も重要なタスクであると判断します
1 Task E
2 Task A
3 Task B
4 Task C
5 Task D
5つのタスクすべてを更新して、新しい優先順位を付ける必要があります。
タスクBがより重要になった場合、Aは
1 Task E
2 Task B
3 Task A
4 Task C
5 Task D
タスクBとAのみを更新する必要があります。
これをDBで構造化するにはどうすればよいですか?同じテーブルに異なるプロジェクトが格納され、独自の重みがあると思います。
その後に実行されるタスクを指す方がよいでしょうか(リンクリストのように)。
これは本当に脳のダンプです。このようなものをどのように実装するのかと思っていたところです。
倍精度浮動小数点数を使用して優先順位を示す場合、順序を変更する必要はありません。
1.00 Task A
2.00 Task B
3.00 Task C
4.00 Task D
5.00 Task E
タスクEをAとBの間に配置したい場合:-
E.priority = B.priority + ((B.priority - A.priority) / 2)
だから今あなたは持っています:
1.00 Task A
1.50 Task E
2.00 Task B
3.00 Task C
4.00 Task D
EとBの間にDを挿入する場合は、優先度を1.75に設定します。浮動小数点数の約18桁の10進数(1.75は実際には1.7500000000000000)を考えると、最悪の場合、前に53の連続した挿入があるはずです。
B.priority + ((B.priority - A.priority) / 2) = B.priority
そして、誰かがdoubleとintegerを使用するオーバーヘッドについて文句を言う前に、データベース内のリストを並べ替える処理とI/Oオーバーヘッドが数桁大きくなるのと比べて、そのハードウェア命令はほんの数個です。
私たちはあなたが話しているまさにこのことをしました。これを行うには、アイテムのリストを並べ替える1つのストアドプロシージャを使用しました。リストの各アイテムには、一意のIDとソート順番号がありました。
例えば:
TaskId int identity(1,1),
Task varchar(50),
SortOrder int
アイテムを並べ替えたストアドプロシージャは、2つの入力パラメーターを取ります。
@TaskId int,
@NewSortOrder int
一時テーブルを使用して、アイテムを新しい順序で格納しました。
CREATE TABLE #Tasks
(
RowId int identity(1,1),
TaskId int
)
3つのselectステートメントを使用して、それらを新しい順序にしました。
-- Step 1
INSERT INTO #Tasks
SELECT TaskId FROM tblTasks
WHERE SortOrder < @NewSortOrder
ORDER BY SortOrder
--Step 2
INSERT INTO #Tasks
VALUES(@TaskId)
--Step 3
INSERT INTO #Tasks
SELECT TaskId FROM tblTasks
WHERE SortOrder >= @NewSortOrder
ORDER BY SortOrder
次に、ベーステーブル(tblTasks)を実際に新しい並べ替え順序で更新しました。 RowId 一時テーブルのID列:
-- Update Base Table
UPDATE tblTasks
SET SortOrder = t2.RowId
FROM tblTasks t1
INNER JOIN #Tasks t2
ON t1.TaskId = t2.TaskId
これは毎回チャンピオンのように機能します。
リンクリストとその操作をRDBMSに実装することは非常に合理的です。配列と参照の操作をSQLクエリに置き換えるだけです。ただし、いくつかの単純な操作では多くのSQLクエリが必要になるため、これが本当に最も効率的な方法であるかどうかはわかりません
タスクテーブルの場合、外部キーである列「next_task」と「prev_task」を同じテーブルのid列に追加します(「-1」はNULLと同等であると想定)
highest_priority()でタスクを返す:prev_task = -1でタスクを返すSQLクエリ
Eが最も重要なタスク:Eのnext_taskを最も優先度の高いタスクのIDに変更するSQLクエリ。そして、Eのprev_taskを-1に変更します...
これと、EをAの前に置く、またはタスクの順序付きリストを印刷するなどのその他の操作では、さらに多くのSQLクエリが必要になります(最適化できない場合)。これは良い練習ですが、おそらく最も効率的な方法ではありません。
優先順位の問題に対する別のアプローチは、アイテムよりも重要なアイテムを指定することです。人事アプリケーションでは、これは従業員の上司が誰であるかを言うようなものです。
ID Name ParentPriority
1 TopPriority NULL
2 Medium 1
3 Low 2
4 AnotherMedium 1
5 Less than 2 2
次にこれを読んでください http://blog.sqlauthority.com/2012/04/24/sql-server-introduction-to-hierarchical-query-using-a-recursive-cte-a-primer/ 優先レベルを与えるクエリを作成します。
ID Name ParentPriority PriorityLevel
1 TopPriority NULL 1
2 Medium 1 2
3 Low 2 3
4 AnotherMedium 1 2
5 Less than 2 2 3
これは、優先度を設定する際のユーザーエクスペリエンスが単純になると思いますが、同じレベルの複数の優先度を使用できます。
私はまだこれを考えていません.....しかし、小数を許可して、すべてを更新せずに他のものの間で詰め込むことができるのはなぜですか?
1.5の値で1と2の間の何かを圧縮することができます。
また、最小値と最大値も避けます。優先度が現在0であるものよりも前にある場合、数値がネガにロールバックすることを許可します。
奇妙な小数や負の値が表示されないようにするには、内部の「順序付け」優先順位とは別に「人間の表示」優先順位を設定することを検討してください。