Lista prioritária de tarefas armazenadas em um banco de dados


10

Estou tentando pensar na melhor maneira de fazer o seguinte:

Eu tenho uma lista de tarefas armazenadas no banco de dados. Uma tarefa tem uma prioridade atribuída a ela. Você pode alterar a prioridade de uma tarefa para reordenar a ordem em que elas devem ser executadas.

Estou pensando em algo muito semelhante ao Pivotal Tracker.

Imagine que tivéssemos o seguinte:

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

Decidimos que E agora é a tarefa mais importante

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

Preciso atualizar todas as 5 tarefas para dar a elas uma nova prioridade.

Se a Tarefa B se tornar mais importante, a IA teria eu

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

Eu preciso atualizar apenas as Tarefas B e A.

De que maneiras a estruturação disso seria feita em um banco de dados? Eu imagino que você teria um projeto diferente armazenado na mesma tabela que teria um peso próprio.

Seria melhor apontar uma tarefa que ocorra após ela (um pouco como uma lista de links).

Este é apenas um despejo cerebral realmente. Só estava me perguntando como você implementaria algo assim.

Respostas:


5
  1. Parece que você está procurando uma fila de prioridade. Você provavelmente não deve recalcular números de prioridade para tarefas, apenas calcula um valor fixo para elas. Se você deseja que a tarefa E seja mais importante, diminua seu valor.
  2. Você está falando essencialmente de relações. B deve ser mais importante do que A. E deve ser a tarefa mais importante, etc .. Parece uma estrutura de árvore, e você pode armazenar isso em um RDBMS com vínculos parentais.

4

Se você usar números de ponto flutuante duplo para indicar prioridade, não precisará solicitar novamente:

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

Se você deseja colocar a tarefa E entre A e B, então: -

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

Então agora você tem:

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

Se você deseja inserir D entre E e B, simplesmente defina sua prioridade como 1,75. Dados os aproximadamente 18 dígitos decimais em um número de ponto flutuante (1,75 é realmente 1,75000000000000000000), você deve ter o pior caso de 53 inserções consecutivas antes:

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

E antes que alguém se queixe da sobrecarga do uso de duplicados versus números inteiros, são apenas algumas instruções de hardware, em comparação com o processamento e a sobrecarga de E / S de reordenar a lista no banco de dados, o que seria várias ordens de magnitude maior.


11
Eu gosto dessa abordagem, mas deve ser: E.priority = A.priority + ((B.priority - A.priority) / 2) e A.priority + ((B.priority - A.priority) / 2) = B.priority
Marcel Panse

1

Fizemos exatamente isso que você está falando. Fizemos isso usando um procedimento armazenado que reordenou a lista de itens. Cada item da lista tinha um ID exclusivo e um número de ordem de classificação.

Por exemplo:

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

O procedimento armazenado que reorganiza os itens leva dois parâmetros de entrada:

@TaskId int,
@NewSortOrder int

Usamos uma tabela temporária para armazenar os itens no novo pedido:

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

Usamos três instruções de seleção para colocá-las no novo pedido:

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

Em seguida, atualizamos a tabela base (tblTasks) com a nova ordem de classificação, que na verdade é a coluna de identidade RowId da tabela temporária:

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

Isso funciona como um campeão sempre.


0

Ainda não pensei nisso ... Mas por que não permitir decimais para que você possa encher coisas entre outras pessoas sem atualizar tudo?

Você pode espremer algo entre 1 e 2 com o valor de 1,5.

Eu também evitaria os valores mínimo e máximo. Permita que os números rolem para os negativos se a prioridade vier antes do que for 0.

Você pode considerar ter uma prioridade de "exibição humana" separada das prioridades internas de "pedido" para evitar mostrar decimais estranhos e valores negativos.


Não use decimais. Use cadeias de caracteres, numéricas ou alfabéticas. Em seguida, você sempre pode inserir um novo valor entre dois antigos, pelo menos até atingir o limite de comprimento da string.
Kevin cline

0

É muito razoável implementar uma lista vinculada e suas operações em um RDBMS. Apenas substitua as manipulações de matriz e referência por consultas SQL. No entanto, não tenho certeza se esse é realmente o caminho mais eficiente, pois algumas operações simples exigirão muitas consultas SQL

Para a tabela de tarefas, você adiciona uma coluna "next_task" e "prev_task", que são chaves estrangeiras na coluna de ID da mesma tabela (supondo que um "-1" seja equivalente a NULL)

Retorne a tarefa com a consulta SQL mais alta () : SQL, que retorna a tarefa com prev_task = -1

E é a tarefa mais importante : consulta SQL que altera a next_task de E para o ID da tarefa com a maior prioridade. E altera prev_task de E para -1 ...

Esta e outras operações, como colocar E antes de A ou imprimir uma lista ordenada de tarefas, exigirão muito mais consultas SQL, que devem ser atômicas (a menos que você possa otimizar). É um bom exercício, mas talvez não seja a maneira mais eficiente de fazê-lo.


0

Outra abordagem para o problema prioritário seria especificar qual item é mais importante que o item. Em um aplicativo de RH, seria como dizer quem é o gerente de um funcionário.

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

Em seguida, leia este http://blog.sqlauthority.com/2012/04/24/sql-server-introduction-to-hierarchical-query-using-a-rrecursive-cte-a-primer/ para fazer uma consulta que dê prioridade níveis.

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

Eu acho que essa é uma experiência mais simples do usuário na definição de prioridades, mas permite várias prioridades do mesmo nível.


-1

Uma maneira simples seria começar com algo assim:

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

Então, para mover a "Tarefa E" entre a Tarefa A e a Tarefa B, digamos, você acabou de definir a prioridade da "Tarefa E" para algo a meio caminho entre a Tarefa A e a Tarefa B (por exemplo, "150" neste caso).

Obviamente, se você reorganizar constantemente as prioridades, acabará encontrando um problema no qual duas tarefas adjacentes não terão "espaço" para inserir novas entradas. Mas quando isso acontece, você pode simplesmente "redefinir" todas as prioridades em uma, voltar para 100, 200, 300, etc.


11
Na verdade, é o mesmo que a minha resposta, apenas começando com números inteiros maiores, em vez de decimais agrupados. :)
jojo

-1

Como não sou um guru de banco de dados, resolvi isso da maneira mais lógica possível no Access 2010. Tenho um campo "Prioridade" que é um campo numérico. Então eu tenho um evento para este campo.

O evento é um evento pós-atualização para o campo "Prioridade" que aciona uma Consulta de Atualização "qryPriority" para adicionar 1 ao número de prioridade de todos os outros registros que têm uma prioridade maior ou igual ao número de prioridade digitado.

Aqui está o código VB do evento e o SQL de consulta de atualização:

Código VB do evento "Priority":

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

Consulta de atualização "qryPriority" SQL:

UPDATE YOURTABLENAME SET YOURTABLENAME.Priority = [Priority]+1
WHERE (((YOURTABLENAME.Priority)>=[Forms]![YOURFORMNAME]![Priority]));
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.