Ordenação no MySQL : lista encadeada rola?

Senhores,

Estou com uma duvida técnica/concentual: preciso fazer um mecanismo de ordenação de entidades.

Imaginem que são Selos em uma Coleção. Tenho a tabela Colecao e a tabela Selo e um Selo esta em uma Colecao.

A ordem que estas fotos aparecem na Coleção pode ser alterada arbitrariamente, na tela o caboclo pode arrastar e soltar as fotos.

Pensei em implementar uma lista encadeada (cada selo sabe qual é o id do proximo) pois assim apenas alguns selos seriam afetados, ao arrastar um eu teria que desfazer apenas 2 nós ao inves de update em 9 ou 25 ou TODOS os selos por exemplo (e na exclusão recriar um nó). Guardar a ordem em um atributo da tabela de coleção me parece ruim.

Como eu vou fazer isso via PHP acessando Mysql eu pergunto:

  1. Eu poderia ordenar pelo SQL usando algo macabro e específico do mysql para retornar os elementos conectados entre si.
  2. Montar essa lista encadeada em memória, via PHP, seria ruim ou menos performático? Sem falar que eu teria que trazer sempre todos, mesmo em caso de paginação, ugh.
  3. SQL recursivo ou algo mais complexo?
  4. Poderia abandonar essa ideia e tratar a ordem como um numero e ordenar por ele, mas ai ao alterar uma posição eu teria que alterar todos os envolvidos, sera que vale a pena (penso em seguir por essa ideia)?
  5. Poderia criar uma XREF maluca e uma maçaroca de SQL que traz tudo ordenado por acaso, uma vez que não faz sentido (via programação por BRUTEFORCE).

Então: sugestões, ofensas, comentários?

Pra banco de dados, o conceito de lista ordenada não existe. Ponto final.

Olhando o seu problema, me veio à cabeça a “solução BASIC”. É assim: você vai usar uma coluna da tabela para definir a ordem, onde a linha com número de menor valor vem antes da linha com número de maior valor. Até aí tudo bem.

O “pulo do gato” é que você não vai atribuir 1, 2, 3 e assim por diante, mas 100, 200, 300… ou seja, números com bastante espaçamento entre si.

Quando você tiver que colocar uma nova foto entre duas adjacentes, cujos “order_number” sejam, por exemplo, 400 e 500; você atualizará o “order_number” da nova foto para 450, ou seja, a média entre os dois (como no BASIC).

Pode haver um problema se o cara fizer arrasta-e-solta muito frequentemente. Talvez chega-se a um momento em que os números adjacentes fiquem próximos demais (do tipo: 1455 e 1456) e não dê pra adicionar uma foto no meio. Aí precisará incrementar por um a foto de “order_number” maior pra caber. E isso continua até achar um número vago.

Não sei se você entendeu, mas é isso aí. Qualquer dúvida, pergunte.

O que tu pode fazer, semelhante à alternativa 2 que você sugeriu, em caso de você não se preocupar mais com o desempenho do que com uso de memoria, é combinar uma lista encadeada com um map de chaves com valores fixos e guardar cada chave de valor fixo do map dentro de cada object que representa o selo.

Dessa Forma, você alia busca rapida (pelo indice você encontra o selo correspondente) e reordenação sem precisar reindexar. Para buscar um selo, você dá apenas um get associado a posicao, que é sempre fixa; no momento de trocar os selos, você usa o get para achar os selos que sofrerão a troca (e essa troca você faz como numa lista encadeada qualquer) e em seguida atualiza os indices de DENTRO do selo sempre mantendo a chave fixa para busca.

T+

[quote=Leonardo3001]Olhando o seu problema, me veio à cabeça a “solução BASIC”. É assim: você vai usar uma coluna da tabela para definir a ordem, onde a linha com número de menor valor vem antes da linha com número de maior valor. Até aí tudo bem.

O “pulo do gato” é que você não vai atribuir 1, 2, 3 e assim por diante, mas 100, 200, 300… ou seja, números com bastante espaçamento entre si.

Quando você tiver que colocar uma nova foto entre duas adjacentes, cujos “order_number” sejam, por exemplo, 400 e 500; você atualizará o “order_number” da nova foto para 450, ou seja, a média entre os dois (como no BASIC).[/quote]

Eu tinha pensado nessa solução porem de tempos em tempos eu poderia fazer um refresh nessa lista caso ocorrece isso de um order number ficar muito proximo.

Imagino que nessa situação,

SELO{id=1, posicao=100}
SELO{id=2, posicao=200}
SELO{id=3, posicao=300}
SELO{id=4, posicao=400}

Se eu quisesse colocar o id 4 no lugar do id 2, empurrando o id 2 para baixo, deixando id 3 pro fim eu teria que fazer

SELO{id=1, posicao=100}
SELO{id=4, posicao=150}
SELO{id=2, posicao=200}
SELO{id=3, posicao=300}

Imagino que, o que eu preciso saber é: vou ficar entre quem e quem. Vou considerar essa solução, até pq não posso implementar nada muito complexo pois testar isso não sera facil pelo pouco tempo que tenho pela frente. Agora vou analisar a solução do MAP do proteu :slight_smile:

Vou te dar uma ideia de mapping que pode ajudar:

imagina que o estado inicial é esse:

0 1 2 3 4

considere que o mapping é “entre quem e quem um numero está situado”:

0 -> (0,0)
1 -> (1,1)
2 -> (2,2)
3 -> (3,3)
4 -> (4,4)

se eu quiser colocar o 4 entre a primeira e a segunda posicao, ficaria assim:

0 -> (0,0)
1 -> (1,1)
2 -> (2,2)
3 -> (3,3)
4 -> (1,2)

a partir daí, teria que pensar como fazer adiante :XD:

T+