Elenco di priorità delle attività memorizzate in un database

8

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

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

Sto pensando a qualcosa di molto simile a Pivotal Tracker.

Quindi immagina di avere il seguente:

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

Decidiamo che E sia 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 diventa più importante allora A I vorrei avere

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

Devo aggiornare solo l'attività B e A.

Quali sono i modi per strutturare questo in un DB? Immagino che avresti un progetto diverso memorizzato nella stessa tabella che avrebbe il proprio peso.

Sarebbe meglio puntare un compito che si svolge dopo di esso (un po 'come un elenco di collegamenti).

Questo è solo un vero e proprio dump del cervello. Mi stavo solo chiedendo come avresti implementato qualcosa di simile.

    
posta Pete 23.07.2011 - 23:23
fonte

8 risposte

5
  1. Sembra che tu stia cercando una coda prioritaria. Probabilmente non dovresti ricalcolare i numeri di priorità per le attività, dovresti semplicemente calcolare un valore fisso per loro. 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 il compito più importante, ecc. Sembra una struttura ad albero, ed è possibile memorizzarlo in un RDBMS con collegamenti padre.
risposta data 24.07.2011 - 00:18
fonte
3

Se si utilizzano numeri a virgola mobile doppi 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, quindi: -

  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, è sufficiente impostare la sua priorità su 1,75. Date le circa 18 cifre decimali in un numero in virgola mobile (1.75 è in realtà 1.7500000000000000) dovresti avere il peggiore dei casi di 53 inserti consecutivi prima:

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

E prima che qualcuno si lamenta del sovraccarico dell'utilizzo di doppio contro interi, sono solo poche istruzioni hardware, rispetto al sovraccarico di elaborazione e I / O di riordino della lista nel database che sarebbe di diversi ordini di grandezza maggiore.

    
risposta data 18.04.2014 - 08:58
fonte
1

Abbiamo fatto proprio questa cosa di cui stai parlando. Lo abbiamo fatto utilizzando una stored procedure che ha riordinato la lista degli articoli. Ogni elemento nell'elenco aveva un ID univoco e un numero di ordinamento.

Ad esempio:

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

La procedura memorizzata che riordina gli elementi richiede 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 select 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 sempre come un campione.

    
risposta data 25.07.2011 - 20:34
fonte
0

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

Potresti 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 priorità viene prima di qualsiasi cosa sia attualmente 0.

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

    
risposta data 24.07.2011 - 04:08
fonte
0

È molto ragionevole implementare un elenco collegato e le sue operazioni in un RDBMS. Basta sostituire la matrice e le manipolazioni di riferimento con le query SQL. Tuttavia, non sono sicuro che questo sia davvero il modo più efficace per andare in quanto 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 (assumendo che un "-1" sia equivalente a NULL)

Restituisci l'attività con il highest_priority () : query SQL che restituisce l'attività con prev_task = -1

E è l'attività più importante : query SQL che modifica il next_task di E all'ID dell'attività con la priorità più alta. E cambia prev_task di E a -1 ...

Questa e altre operazioni come mettere E prima di A, o stampare un elenco ordinato di attività richiederà 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ù efficace per farlo.

    
risposta data 24.07.2011 - 11:43
fonte
0

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 l'attività A e l'attività B, ad esempio, devi semplicemente impostare la priorità di "Task E" su qualcosa a metà tra l'attività A e l'attività B (cioè "150" in questo caso).

Naturalmente, se ridisposti costantemente le priorità, alla fine ti imbatterai in un problema in cui due attività adiacenti non hanno "spazio" per inserire nuove voci. Ma quando ciò accade, puoi semplicemente "resettare" tutte le priorità in una tornata a 100, 200, 300, ecc.

    
risposta data 24.07.2011 - 12:31
fonte
0

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

L'evento è un evento successivo all'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

"qryPriority" Query di aggiornamento SQL:

UPDATE YOURTABLENAME SET YOURTABLENAME.Priority = [Priority]+1
WHERE (((YOURTABLENAME.Priority)>=[Forms]![YOURFORMNAME]![Priority]));
    
risposta data 23.01.2014 - 21:34
fonte
0

Un altro approccio al problema prioritario sarebbe quello di specificare quale elemento è più importante dell'elemento. In un'applicazione HR, 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

Poi leggi questo link per creare una query che fornisca livelli di priorità.

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 nell'impostazione delle priorità, ma consente più priorità dello stesso livello.

    
risposta data 05.12.2016 - 19:05
fonte

Leggi altre domande sui tag