Lista prioritaria de tareas almacenadas en una base de datos

10

Estoy tratando de pensar en la mejor manera de hacer lo siguiente:

Tengo una lista de tareas almacenadas en la base de datos. Una tarea tiene una prioridad asignada. Puede cambiar la prioridad de una tarea para reordenar el orden en que deben llevarse a cabo.

Estoy pensando en algo muy similar a Pivotal Tracker.

Entonces imagina que tenemos lo siguiente:

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

Decidimos que E es ahora la tarea más importante

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

Necesito actualizar las 5 tareas para darles una nueva prioridad.

Si la Tarea B se vuelve más importante, entonces la IA tendría

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

Necesito actualizar la Tarea B y A solamente.

¿De qué manera se estructuraría esto en un DB? Me imagino que tendrías diferentes proyectos almacenados en la misma tabla que tendrían su propio peso.

¿Sería mejor señalar una tarea que se lleva a cabo después (un poco como una lista de enlaces)?

Esto es solo un tugurio en realidad. Solo me preguntaba cómo harías para implementar algo como esto.

Pete
fuente

Respuestas:

5
  1. Parece que estás buscando una cola prioritaria. Probablemente no debería volver a calcular los números de prioridad para las tareas, solo debe calcular un valor fijo para ellas. Si desea que la tarea E sea más importante, disminuya su valor.
  2. Básicamente estás hablando de relaciones. B debería ser más importante que A. E debería ser la tarea más importante, etc. Parece una estructura de árbol, y puede almacenarla en un RDBMS con enlaces primarios.
Karoly Horvath
fuente
4

Si usa números de coma flotante doble para indicar la prioridad, no necesita volver a ordenar:

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

Si desea colocar la tarea E entre A y B, entonces: -

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

Entonces ahora tienes:

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

Si desea insertar D entre E y B, simplemente establezca su prioridad en 1.75. Dados los aproximadamente 18 dígitos decimales en un número de coma flotante (1.75 es realmente 1.7500000000000000), debería tener el peor de los casos de 53 inserciones consecutivas antes:

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

Y antes de que alguien se queje de la sobrecarga del uso de dobles contra enteros, son solo unas pocas instrucciones de hardware, en comparación con el procesamiento y la carga de E / S de reordenar la lista en la base de datos, que sería varios órdenes de magnitud mayor.

James Anderson
fuente
1
Me gusta este enfoque, pero debería ser: E.priority = A.priority + ((B.priority - A.priority) / 2) y A.priority + ((B.priority - A.priority) / 2) = B. prioridad
Marcel Panse
1

Hicimos esto mismo de lo que estás hablando. Lo hicimos utilizando un procedimiento almacenado que reordenó la lista de elementos. Cada elemento de la lista tenía una identificación única y un número de orden de clasificación.

Por ejemplo:

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

El procedimiento almacenado que reordena los elementos toma dos parámetros de entrada:

@TaskId int,
@NewSortOrder int

Utilizamos una tabla temporal para almacenar los artículos en el nuevo orden:

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

Utilizamos tres declaraciones selectas para colocarlas en el nuevo orden:

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

Luego actualizamos la tabla base (tblTasks) con el nuevo orden de clasificación, que en realidad es la columna de identidad RowId de la tabla temporal:

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

Esto funciona como un campeón cada vez.

Michael Riley - también conocido como Gunny
fuente
0

Todavía no he pensado en esto ..... ¿Pero por qué no solo permitir decimales para que puedas meter cosas entre otros sin actualizar todo?

Podría aplastar algo entre 1 y 2 con el valor de 1.5.

También evitaría los valores mínimo y máximo. Permita que los números lleguen a los negativos si la prioridad viene antes de lo que sea actualmente 0.

Puede considerar tener una prioridad de "visualización humana" separada de las prioridades internas de "ordenar" para evitar mostrar decimales extraños y valores negativos.

jojo
fuente
No uses decimales. Utilice cadenas, numéricas o alfabéticas. Luego, siempre puede insertar un nuevo valor entre dos valores antiguos, al menos hasta alcanzar el límite de longitud de la cadena.
Kevin Cline
0

Es muy razonable implementar una Lista Vinculada y sus operaciones en un RDBMS. Simplemente reemplace las manipulaciones de matriz y referencia con consultas SQL. Sin embargo, no estoy seguro de si esta es realmente la forma más eficiente de hacerlo, ya que algunas operaciones simples requerirán muchas consultas SQL

Para la tabla de tareas, agregue una columna "next_task" y "prev_task" que son claves foráneas a la columna id de la misma tabla (suponiendo que un "-1" sea equivalente a NULL)

Devuelve la tarea con la mayor prioridad () : consulta SQL que devuelve la tarea con prev_task = -1

E es la tarea más importante : consulta SQL que cambia la siguiente tarea de E al ID de la tarea con la prioridad más alta. Y cambia prev_task de E a -1 ...

Esta y otras operaciones, como poner E antes de A, o imprimir una lista ordenada de tareas requerirán muchas más consultas SQL, que deberían ser todas atómicas (a menos que pueda optimizar). Es un buen ejercicio, pero quizás no sea la forma más eficiente de hacerlo.

S.S
fuente
0

Otro enfoque del problema de prioridad sería especificar qué elemento es más importante que el elemento. En una aplicación de recursos humanos, esto sería como decir quién es el gerente de un empleado.

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

Luego lea este http://blog.sqlauthority.com/2012/04/24/sql-server-introduction-to-hierarchical-query-using-a-recursive-cte-a-primer/ para hacer una consulta que da prioridad niveles.

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

Creo que esta es una experiencia de usuario más simple para establecer prioridades, pero permite múltiples prioridades del mismo nivel.

Steven Brown
fuente
-1

Una manera simple sería comenzar con algo como esto:

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

Luego, para mover la "Tarea E" entre la Tarea A y la Tarea B, digamos, simplemente establecería la prioridad de la "Tarea E" en algo a medio camino entre la Tarea A y la Tarea B (es decir, "150" en este caso).

Por supuesto, si constantemente reorganiza las prioridades, eventualmente se encontrará con un problema por el cual dos tareas adyacentes no tienen "espacio" para insertar nuevas entradas. Pero cuando eso sucede, simplemente puede "restablecer" todas las prioridades de una vez, volver a 100, 200, 300, etc.

Dean Harding
fuente
1
Esto es realmente lo mismo que mi respuesta, solo comenzando con enteros más grandes en lugar de decimales agrupados estrechamente. :)
jojo
-1

No soy un gurú de bases de datos, por lo que resolví esto de la manera más lógica que pude en Access 2010. Tengo un campo de "Prioridad" que es un campo numérico. Entonces tengo un evento para este campo.

El evento es un evento posterior a la actualización para el campo "Prioridad" que activa una consulta de actualización "qryPriority" para agregar 1 al número de prioridad de todos los demás registros que tienen una prioridad mayor o igual al número de prioridad recién ingresado.

Aquí está el código del evento VB y Update Query SQL:

Código VB del 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 de consulta de actualización "qryPriority":

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