Liste prioritaire des tâches stockées dans une base de données

10

J'essaie de penser à la meilleure façon de procéder comme suit:

J'ai une liste de tâches stockées dans la base de données. Une tâche a une priorité qui lui est affectée. Vous pouvez modifier la priorité d'une tâche pour réorganiser l'ordre de leur exécution.

Je pense à quelque chose de très similaire à Pivotal Tracker.

Imaginez donc que nous avions les éléments suivants:

1 Task A
2 Task B
3 Task C
4 Task D
5 Task E

Nous décidons que E est maintenant la tâche la plus importante

1 Task E
2 Task A
3 Task B
4 Task C
5 Task D

Je dois mettre à jour les 5 tâches pour leur donner une nouvelle priorité.

Si la tâche B devient alors plus importante, l'IA l'aurais-je

1 Task E
2 Task B
3 Task A
4 Task C
5 Task D

Je dois mettre à jour les tâches B et A uniquement.

Quelles façons de structurer cela dans une base de données? J'imagine que vous auriez un projet différent stocké dans la même table qui aurait son propre poids.

Serait-il préférable de pointer une tâche qui a lieu après (un peu comme une liste de liens).

Ce n'est vraiment qu'une décharge de cerveau. Je me demandais simplement comment vous alliez procéder pour mettre en œuvre quelque chose comme ça.

Pete
la source

Réponses:

5
  1. Il semble que vous recherchiez une file d'attente prioritaire. Vous ne devriez probablement pas recalculer les numéros de priorité pour les tâches, vous devez simplement calculer une valeur fixe pour celles-ci. Si vous voulez que la tâche E soit plus importante, diminuez sa valeur.
  2. Vous parlez essentiellement de relations. B devrait être plus important que A. E devrait être la tâche la plus importante, etc. Cela ressemble à une structure arborescente, et vous pouvez le stocker dans un SGBDR avec des liens parents.
Karoly Horvath
la source
5

Si vous utilisez des nombres à virgule flottante double pour indiquer la priorité, vous n'avez pas besoin de réorganiser:

1.00 Task A
2.00 Task B
3.00 Task C
4.00 Task D
5.00 Task E

Si vous souhaitez placer la tâche E entre A et B, alors: -

  E.priority = B.priority + ((B.priority - A.priority) / 2)

Alors maintenant, vous avez:

1.00 Task A
1.50 Task E
2.00 Task B
3.00 Task C
4.00 Task D

Si vous souhaitez insérer D entre E et B, définissez simplement sa priorité sur 1,75. Étant donné les 18 chiffres décimaux environ dans un nombre à virgule flottante (1,75 est vraiment 1,7500000000000000), vous devriez avoir un pire cas de 53 insertions consécutives avant:

 B.priority + ((B.priority - A.priority) / 2) = B.priority

Et avant que quiconque ne se plaint du surcoût lié à l'utilisation de doublons par rapport à des entiers, ce ne sont que quelques instructions matérielles, par rapport au traitement et aux frais d'E / S de réorganisation de la liste dans la base de données, qui seraient de plusieurs ordres de grandeur plus importants.

James Anderson
la source
1
J'aime cette approche, mais elle devrait être: E.priority = A.priority + ((B.priority - A.priority) / 2) et A.priority + ((B.priority - A.priority) / 2) = B.priority
Marcel Panse
1

Nous avons fait exactement ce dont vous parlez. Nous l'avons fait en utilisant une procédure stockée qui a réorganisé la liste des éléments. Chaque élément de la liste avait un identifiant unique et un numéro d'ordre de tri.

Par exemple:

TaskId int identity(1,1),
Task varchar(50),
SortOrder int

La procédure stockée qui réorganise les éléments prend deux paramètres d'entrée:

@TaskId int,
@NewSortOrder int

Nous avons utilisé une table temporaire pour stocker les articles dans la nouvelle commande:

CREATE TABLE #Tasks
(
RowId int identity(1,1),
TaskId int
)

Nous avons utilisé trois instructions select pour les insérer dans la nouvelle commande:

-- 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

Nous avons ensuite mis à jour la table de base (tblTasks) avec le nouvel ordre de tri qui est en fait la colonne d'identité RowId de la table temporaire:

-- Update Base Table
UPDATE tblTasks
SET SortOrder = t2.RowId
FROM tblTasks t1
INNER JOIN #Tasks t2
ON t1.TaskId = t2.TaskId

Cela fonctionne comme un champion à chaque fois.

Michael Riley - AKA Gunny
la source
0

Je n'ai pas encore réfléchi à cela ..... Mais pourquoi ne pas simplement autoriser les décimales pour pouvoir farcir les choses entre les autres sans tout mettre à jour?

Vous pouvez écraser quelque chose entre 1 et 2 avec une valeur de 1,5.

J'éviterais également les valeurs min et max. Permettez aux nombres de rouler dans les négatifs s'ils sont prioritaires avant ce qui est actuellement 0.

Vous pouvez envisager d'avoir une priorité "d'affichage humain" distincte des priorités internes "d'ordre" pour éviter d'afficher des décimales bizarres et des valeurs négatives.

jojo
la source
N'utilisez pas de décimales. Utilisez des chaînes, numériques ou alphabétiques. Ensuite, vous pouvez toujours insérer une nouvelle valeur entre deux anciennes, au moins jusqu'à ce que vous atteigniez la limite de longueur de chaîne.
kevin cline
0

Il est très raisonnable d'implémenter une liste liée et ses opérations dans un SGBDR. Remplacez simplement les manipulations de tableaux et de références par des requêtes SQL. Cependant, je ne suis pas sûr que ce soit vraiment le moyen le plus efficace car certaines opérations simples nécessiteront de nombreuses requêtes SQL

Pour la table des tâches, vous ajoutez une colonne "next_task" et "prev_task" qui sont des clés étrangères à la colonne id de la même table (en supposant qu'un "-1" équivaut à NULL)

Renvoyer la tâche avec la requête le plus élevé_priority () : SQL qui renvoie la tâche avec prev_task = -1

E est la tâche la plus importante : la requête SQL qui change la next_task de E en l'ID de la tâche avec la priorité la plus élevée. Et change prev_task de E en -1 ...

Cela et d'autres opérations comme mettre E avant A ou imprimer une liste ordonnée de tâches nécessiteront beaucoup plus de requêtes SQL qui devraient être toutes atomiques (sauf si vous êtes en mesure d'optimiser). C'est un bon exercice mais ce n'est peut-être pas la façon la plus efficace de le faire.

HH
la source
0

Une autre approche du problème prioritaire consisterait à spécifier quel élément est plus important que l'élément. Dans une application RH, cela reviendrait à dire qui est le manager d'un employé.

ID  Name           ParentPriority
1   TopPriority    NULL
2   Medium         1
3   Low            2
4   AnotherMedium  1
5   Less than 2    2

Lisez ensuite ce http://blog.sqlauthority.com/2012/04/24/sql-server-introduction-to-hierarchical-query-using-a-recursive-cte-a-primer/ pour faire une requête qui donne la priorité niveaux.

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

Je pense que c'est une expérience utilisateur plus simple dans la définition des priorités, mais cela permet de multiples priorités du même niveau.

Steven Brown
la source
-1

Une façon simple serait de commencer avec quelque chose comme ceci:

100 Task A
200 Task B
300 Task C
400 Task D
500 Task E

Ensuite, pour déplacer la "Tâche E" entre la Tâche A et la Tâche B, disons, vous venez de définir la priorité de la "Tâche E" à quelque chose à mi-chemin entre la Tâche A et la Tâche B (c'est-à-dire "150" dans ce cas).

Bien sûr, si vous réorganisez constamment les priorités, vous finirez par rencontrer un problème selon lequel deux tâches adjacentes n'ont pas de "trou" pour insérer de nouvelles entrées. Mais lorsque cela se produit, vous pouvez simplement "réinitialiser" toutes les priorités en un seul retour à 100, 200, 300, etc.

Dean Harding
la source
1
C'est en fait la même chose que ma réponse, commençant juste avec des entiers plus grands au lieu de décimales étroitement groupées. :)
jojo
-1

Je ne suis pas un gourou de la base de données, j'ai donc résolu cela de la manière la plus logique possible dans Access 2010. J'ai un champ "Priority" qui est un champ numérique. Ensuite, j'ai un événement pour ce domaine.

L'événement est un événement après mise à jour pour le champ "Priority" qui déclenche une requête de mise à jour "qryPriority" pour ajouter 1 au numéro de priorité de tous les autres enregistrements qui ont une priorité supérieure ou égale au numéro de priorité qui vient d'être entré.

Voici le code VB de l'événement et la mise à jour de la requête SQL:

Code VB de l'événement "Priority":

Private Sub Priority_AfterUpdate()
Me.Refresh
If Priority > 0 Then
DoCmd.OpenQuery ("qryPriority")
End If
Me.Refresh
Priority = Priority - 1
End Sub

"qryPriority" Mettre à jour la requête SQL:

UPDATE YOURTABLENAME SET YOURTABLENAME.Priority = [Priority]+1
WHERE (((YOURTABLENAME.Priority)>=[Forms]![YOURFORMNAME]![Priority]));
Keegan
la source