2014-04-14 12 views
6

Supponiamo di avere una tabella MySQL (id, nome) e una vista elenco abilitata per trascinamento della tabella. L'utente trascina la 90a riga e la posiziona sopra la 10a riga. Qual è l'approccio migliore per mantenere questo nuovo ordinamento?
Qual è l'approccio migliore per ordinare le righe della tabella MySQL in base alla scelta dell'utente?

  • I do not mean to keep sorting for every use separately
  • The HTML/JavaScript is not the problem

Ho visto alcuni programmatori aggiungono una colonna di peso a tavola, l'impostazione numero più basso in alto nella tabella. Nel mio esempio sarà compreso tra 1 e 100. Il problema è nel caso dell'esempio sopra (da 90 a 10) l'aggiornamento di 81 righe è richiesto. 90 modifiche a 10 e ogni 10 a 89 incrementi. È efficiente in MySQL? C'è una soluzione migliore?
Un altro modo è salvare il nuovo ordine come una stringa in un'altra tabella, ma in questo caso perdiamo l'ordinamento MySQL in fase di recupero!

Mi ricordo quando abbiamo appreso struttura ad albero trie in università come uno strumento di indicizzazione , abbiamo detto wow! Anche quando abbiamo sfruttato ogni singolo bit di un byte , 1,5 GB di dati di testo puro memorizzati in meno di 500 KB !!! Quindi adesso sto ancora cercando una risposta migliore!

risposta

0

Invece di aggiungere una colonna weight alla tabella MYSQL, aggiungere una colonna next_object alla tabella.

Funzionerebbe come una lista collegata (se si ha familiarità con quello). Ogni oggetto inserito punterà al prossimo oggetto.

Andiamo attraverso lo scenario di spostamento di un oggetto di posizione 90 alla posizione 10.

In primo luogo, è necessario aggiornare l'oggetto 89 ° in modo che ora punta all'oggetto 91a (il nuovo oggetto 90a)

Quindi, è necessario aggiornare il 9 ° oggetto e farlo puntare al 90 ° oggetto (il nuovo 10 ° oggetto)

Infine, è necessario aggiornare il 90 ° oggetto (il nuovo 10 ° oggetto) e farlo puntare a il 10 ° oggetto (il nuovo undicesimo oggetto)

Ovviamente, per punto, aggiorno il campo next_object all'oggetto che sto indicando.

Cosa si può inserire esattamente come valore nel campo next_object? Solo l'ID dell'oggetto o qualcosa di simile.

Ho appena trovato questo sistema come alternativa quando ho iniziato a scrivere questa risposta, quindi non sono sicuro che sia il modo più efficace. Ma hey, l'aggiornamento di 3 oggetti è meglio di un potenziale 100.000 (se tu avessi 100.000 oggetti).

+0

Immagino tu intenda "Elenco collegato", non lo Stack. Ci ho pensato prima, ma in questo caso perdiamo l'ordinamento MySQL in fase di recupero! – HPM

+0

Ho pubblicato un'altra risposta. –

2

Anche i linguaggi di programmazione durante l'aggiornamento degli indici per un array che aveva aggiunto un oggetto in un indice precedentemente occupato ne aggiungono uno a ciascun indice.

È necessario terminare l'aggiornamento dell'indice per ogni singola riga.

Il modo più pulito per farlo comunque sarebbe qualcosa come questo (in cui la gente è una tabella non banale ovviamente):

UPDATE people 
SET index = index + 1 
WHERE index BETWEEN $newIndex AND $oldIndex; 

a seconda della base di dati, tra potrebbe includere o escludere l'alto e basso legati numeri. Assicurati solo di sapere come li tratta!

+0

grazie, al momento mi assicuro che non ci sia una soluzione migliore, inizio a implementare la soluzione per il peso. Ci sto ancora provando! – HPM

0

Finalmente, ho fatto l'ordinamento con questo metodo: ho creato una colonna di peso. Ogni riga dopo l'inserimento ottiene il suo id come valore di peso. Assicura che la nuova riga sarà alla fine. la colonna di peso è di tipo FLOAT. Jquery aiuta a ottenere una nuova posizione della riga, più la riga della tabella prev() e next(). Giusto nuovo abbiamo tre situazioni che sono commentati nel frammento vuoto sanitario (Dopo retriving ID dalle righe e invio Ajax PHP):

#table of DB 
    $table = $_POST['table']; 
    #the id of the row on top 
    $t = $_POST['t']; 
    #the id of the row on middle 
    $m = $_POST['m']; 
    #the id of the row on bottom 
    $b = $_POST['b']; 
    switch ('') { 
     #top is empty, so the row is droped on top 
     case $t: 
      #we set middle weigh 0.5 lower than its bottom 
      $query = " 
       UPDATE `$table` m, `$table` b 
       SET m.`weight` = b.`weight`-0.5 
       WHERE m.`id` = $m 
       AND b.`id` = $b 
      "; 
      break; 
     #bottom is empty, so the row is droped on the end 
     case $b: 
      #we set middle weigh 0.5 upper than its top 
      $query = " 
       UPDATE `$table` m, `$table` t 
       SET m.`weight` = t.`weight`+0.5 
       WHERE m.`id` = $m 
       AND t.`id` = $t 
      "; 
      break; 
     #values are not empty, so the row is droped in the middle part 
     default: 
      #we set middle weigh exactly between top and bottom 
      $query = " 
       UPDATE `$table` m, `$table` t, `$table` b 
       SET m.`weight` = (t.`weight`+b.`weight`)/2 
       WHERE m.`id` = $m 
       AND t.`id` = $t 
       AND b.`id` = $b 
      "; 
      break; 
    } 
    Yii::app()->db->createCommand($query)->query(); 

Anche dopo 45 volte di divisione 1 a 2, valore galleggiante non scenderà a zero , quindi questa soluzione è un rimedio adesso!

Problemi correlati