Elenco di priorità delle attività archiviate in un database


10

Sto cercando di pensare al modo migliore per fare quanto segue:

Ho un elenco di attività archiviate nel database. A un'attività è assegnata una priorità. È possibile modificare la priorità di un'attività per riordinare l'ordine in cui devono essere eseguite.

Sto pensando a qualcosa di molto simile a Pivotal Tracker.

Quindi immagina di avere quanto segue:

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

Decidiamo che E è ora il compito più importante

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

Devo aggiornare tutte e 5 le attività per dare loro una nuova priorità.

Se l'attività B diventasse più importante, allora l'AI lo avrei

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

Devo aggiornare solo le attività B e A.

In che modo si potrebbe strutturare questo in un DB? Immagino che avresti un progetto diverso memorizzato nella stessa tabella che avrebbe il suo peso.

Sarebbe meglio indicare un'attività che si svolge dopo di essa (un po 'come un elenco di collegamenti).

Questa è solo una discarica del cervello. Mi chiedevo solo come avresti potuto implementare qualcosa del genere.

Risposte:


5
  1. Sembra che tu stia cercando una coda prioritaria. Probabilmente non dovresti ricalcolare i numeri di priorità per le attività, devi semplicemente calcolare un valore fisso per esse. Se vuoi che l'attività E sia più importante, riduci il valore.
  2. Stai essenzialmente parlando di relazioni. B dovrebbe essere più importante di A. E dovrebbe essere l'attività più importante, ecc. Sembra una struttura ad albero e puoi memorizzarla in un RDBMS con collegamenti principali.

4

Se si utilizzano doppi numeri in virgola mobile per indicare la priorità, non è necessario riordinare:

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

Se si desidera posizionare l'attività E tra A e B, allora: -

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

Quindi ora hai:

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

Se si desidera inserire D tra E e B, impostare semplicemente la priorità su 1,75. Date le circa 18 cifre decimali in un numero in virgola mobile (1,75 è in realtà 1.750000000000000000) si dovrebbe avere un caso peggiore di 53 inserimenti consecutivi prima di:

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

E prima che qualcuno si lamenti dell'overhead dell'uso di doppi contro numeri interi, sono solo alcune istruzioni hardware, rispetto all'overhead di elaborazione e I / O di riordinare l'elenco nel database che sarebbe maggiore di molti ordini di grandezza.


1
Mi piace questo approccio, ma dovrebbe essere: E.priority = A.priority + ((B.priority - A.priority) / 2) e A.priority + ((B.priority - A.priority) / 2) = B.priority
Marcel

1

Abbiamo fatto proprio questa cosa di cui stai parlando. Lo abbiamo fatto utilizzando una procedura memorizzata che ha riordinato l'elenco di elementi. Ogni articolo nell'elenco aveva un ID univoco e un numero di ordinamento.

Per esempio:

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

La procedura memorizzata che riordina gli elementi accetta due parametri di input:

@TaskId int,
@NewSortOrder int

Abbiamo usato una tabella temporanea per memorizzare gli articoli nel nuovo ordine:

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

Abbiamo usato tre istruzioni selezionate per inserirle nel nuovo ordine:

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

Abbiamo quindi aggiornato la tabella di base (tblTasks) con il nuovo ordinamento che è in realtà la colonna di identità RowId della tabella temporanea:

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

Funziona come un campione ogni volta.


0

Non ci ho ancora pensato ..... Ma perché non consentire solo i decimali in modo da poter riempire le cose tra gli altri senza aggiornare tutto?

Puoi schiacciare qualcosa tra 1 e 2 con il valore di 1,5.

Eviterei anche i valori minimo e massimo. Consenti ai numeri di passare ai negativi se la loro priorità precede qualunque sia attualmente 0.

Puoi considerare di avere una priorità di "visualizzazione umana" separata dalle priorità interne di "ordinamento" per evitare di mostrare decimali bizzarri e valori negativi.


Non usare i decimali. Usa stringhe, numeriche o alfabetiche. Quindi puoi sempre inserire un nuovo valore tra due vecchi, almeno fino a raggiungere il limite di lunghezza della stringa.
Kevin Cline il

0

È molto ragionevole implementare un elenco collegato e le sue operazioni in un RDBMS. Sostituisci le manipolazioni di array e riferimenti con query SQL. Tuttavia, non sono sicuro che questo sia davvero il modo più efficiente di procedere poiché alcune semplici operazioni richiederanno molte query SQL

Per la tabella delle attività, aggiungi una colonna "next_task" e "prev_task" che sono chiavi esterne alla colonna id della stessa tabella (supponendo che un "-1" equivale a NULL)

Restituisce l'attività con la quota più alta () : query SQL che restituisce l'attività con prev_task = -1

E è l'attività più importante : query SQL che modifica il prossimo task di E nell'ID dell'attività con la massima priorità. E cambia prev_task di E in -1 ...

Questa e altre operazioni come mettere E prima di A o stampare un elenco ordinato di attività richiederanno molte più query SQL che dovrebbero essere tutte atomiche (a meno che tu non sia in grado di ottimizzare). È un buon esercizio ma forse non è il modo più efficiente di farlo.


0

Un altro approccio al problema prioritario sarebbe quello di specificare quale elemento è più importante dell'elemento. In un'applicazione per le risorse umane, sarebbe come dire chi è il manager di un dipendente.

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

Quindi leggi questo http://blog.sqlauthority.com/2012/04/24/sql-server-introduction-to-hierarchical-query-using-a-recursive-cte-a-primer/ per fare una query che dia priorità livelli.

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

Penso che questa sia un'esperienza utente più semplice nella definizione delle priorità, ma consente più priorità dello stesso livello.


-1

Un modo semplice sarebbe iniziare con qualcosa del genere:

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

Quindi, per spostare "Task E" tra Task A e Task B, diciamo, devi solo impostare la priorità di "Task E" su qualcosa a metà strada tra Task A e Task B (ovvero "150" in questo caso).

Naturalmente, se riorganizzi costantemente le priorità, alla fine ti imbatterai in un problema in base al quale due attività adiacenti non hanno "gap" per inserire nuove voci. Ma quando ciò accade, puoi semplicemente "reimpostare" tutte le priorità in una per tornare a 100, 200, 300, ecc.


1
Questa è in realtà la stessa della mia risposta, appena iniziato con numeri più grandi invece di decimali strettamente raggruppati. :)
jojo

-1

Non sono un guru del database, quindi ho risolto il problema nel modo più logico possibile in Access 2010. Ho un campo "Priorità" che è un campo numerico. Quindi ho un evento per questo campo.

L'evento è un evento post-aggiornamento per il campo "Priorità" che attiva una query di aggiornamento "qryPriority" per aggiungere 1 al numero di priorità di tutti gli altri record che hanno una priorità maggiore o uguale al numero di priorità appena inserito.

Ecco il codice VB dell'evento e SQL Query di aggiornamento:

Codice VB evento "prioritario":

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

SQL query di aggiornamento "qryPriority":

UPDATE YOURTABLENAME SET YOURTABLENAME.Priority = [Priority]+1
WHERE (((YOURTABLENAME.Priority)>=[Forms]![YOURFORMNAME]![Priority]));
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.