Pergunta

Eu tenho uma tabela de registros no MySQL. Eu preciso para manter uma ordem para eles como especificado pelo usuário. Então eu adicionei uma coluna de 'posição'.

Qual seria a instrução SQL para atualizar todos os registros quando eu passar um registro específico? Eu tenho algo como:

UPDATE items SET position = '2' WHERE id ='4';
UPDATE items SET position = position+1 WHERE position >= '2' AND id != '4';

Mas o maior que vai ser um menos do que se o registro foi movido para baixo. Qual é o truque? Obrigado!

Foi útil?

Solução

fazendo esse tipo de coisa para por exemplo ordens de venda com números de linhas mantidas pelo usuário, eu achei melhor para lidar com isso de uma matriz no BL ou UI. Normalmente eles vão querer ajustar vários registros, e às vezes quero dizer "esquecê-lo". Então, o mais fácil poderia ser a de simplesmente esperar até que atingiu o botão "OK" (ou seu equivalente) e, em seguida, escrevê-los todos de volta com ordenação atual.

Você pode acabar lidar com eliminações, também, que é um outro problema que você pode lidar com a mesma forma.

Outras dicas

Será que algo assim fazê-lo?

UPDATE items 
SET position = CASE position 
  WHEN $oldpos THEN $newpos 
  ELSE position + SIGN($oldpos-$newpos)
 END
WHERE position BETWEEN LEAST( $newpos, $oldpos ) 
                AND GREATEST( $newpos, $oldpos );

Eu testei um par de vezes e parece trabalho.

Esta é minha tomada neste: minha coluna ROW_INDEX tem número com um passo de 10 (por ex .: 0, 10, 20, ecc.). Quando um usuário atualiza um da linha que você precisa saber se ele vai para cima ou para baixo. Se você tem que mover a linha 2 para o 4º (indo para baixo, ROW_INDEX desejado = 30), você define o ROW_INDEX a 35; caso contrário (se a subir) configurá-lo para 25. Definir este valor:

UPDATE your_table SET row_index = 35 WHERE your_id = 1234

Agora você tem a ordem correta, mas os row_indexes estão bagunçados. Para corrigir isso, executar esta duas consultas:

SET @pos:=-10;
UPDATE your_table SET row_index = @pos:=@pos+10 WHERE ...

Isso vai atualizar todos os seus linhas (ou o que você selecionar com o qual declaração) e definir a coluna ROW_INDEX sem intervalos (0, 10, 20, 30, ecc.). Certamente desta forma adiciona carga sobre as operações de gravação, mas eu acho que é a maneira mais rápida para obter a ordem durante as operações de leitura. Se você excluir uma linha você pode simplesmente re executar as consultas de pedidos de fixação.

Gostaria de sugerir, no mínimo, usando grandes incrementos (dizer 10000) entre os itens. Em seguida, basta fazer um pedido por. Se você precisa mover 11000 para entre 9000 e 10000, em seguida, basta configurá-lo para 9500 e feito.

Esta não elimina o problema de reordenamento mas reduz muito isso. Em algum momento você é melhor fora de exclusão de todas as linhas, em seguida, readding-los com a ordem correta. Fazer atualizações como você está fazendo é simplesmente muito erro imho propenso.

Você pode considerar o uso de um tipo de lista encadeada de abordagem, com uma chave para a próxima, e talvez o item anterior na lista, então você só tem que atualizar alguns registros, em vez de todos eles.

Interessante! Ok, então não há uma resposta fácil. Eu achava que estava apenas faltando alguma coisa. Eu tinha pensado sobre a manutenção de um conjunto externo. Isso soa como a melhor idéia.

Talvez algo como isso?

$item_id = $_GET['item_id']; 
$position = $_GET['new_position']; 
$old_position = $_GET['old_position'];

if($new_position < $old_position) {
    SQL: UPDATE items SET position = position+1 WHERE position >= $new_position AND position < $old_position  
} else {  
SQL: UPDATE items SET position = position-1 WHERE position <= $new_position AND position > $old_position
}  

SQL: UPDATE items SET position = $new_position WHERE item_id = $item_id 
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top