Mysql
 sql >> Database >  >> RDS >> Mysql

Impaginazione basata su cursore MySQL con più colonne

If (il nome sfortunato) colonna Column_1 è unico, potresti semplicemente fare:

 WHERE Column_1 > :last_retrieved_value

Dalla domanda, sembra che Column_1 non è univoco, ma il (Column_1,Column_2) la tupla è unica.

Il modulo generale per una query "pagina successiva", ordinando in base a queste due colonne, utilizzando gli ultimi valori recuperati per quelle due colonne, sarebbe...

    (Column1,Column2) > (:lrv_col1,:lrv_col2)

(lrv =valore salvato dall'ultima riga recuperata dalla query precedente)

Per scrivere quella condizione in MySQL, possiamo farlo come hai mostrato:

 WHERE t.Column_1 > :lrv_col1
    OR ( t.Column_1 = :lrv_col1 AND t.Column_2 > :lrv_col2 )

Oppure potremmo scriverlo in questo modo, cosa che preferisco, perché c'è molto meno possibilità che MySQL venga confuso dalla condizione OR e usi l'indice sbagliato...

 WHERE t.Column_1 >= :lrv_col1
       AND ( t.Column_1 > :lrv_col1 OR t.Column_2 > :lrv_col2 )
 ORDER BY t.Column_1, t.Column_2
 LIMIT n

Per estenderlo a tre colonne, per verificare la condizione...

  (c1,c2,c3) > (:lrv1,:lrv2,:lrv3)

Lo gestiamo proprio come nel caso di due colonne, gestendo c1 per prima cosa, suddividendolo proprio come le due colonne:

 WHERE c1 >= :lrv1
       AND ( c1 > :lrv1 OR ( ... ) )
 ORDER BY c1, c2, c3
 LIMIT n

E ora quel segnaposto ... (dove avrebbe avuto solo il controllo su c2 prima, è davvero di nuovo solo un altro caso di due colonne. Dobbiamo controllare:(c2,c3) > (lrv2,lrv3) , quindi possiamo espanderlo usando lo stesso schema:

 WHERE c1 >= :lrv1
       AND ( c1 > :lrv1 OR ( c2 >= :lrv2 
                             AND ( c2 > :lrv2 OR c3 > :lrv3 )
                           )
           )
 ORDER BY c1,c2,c3
 LIMIT n

Sono d'accordo sul fatto che l'espansione possa sembrare un po' disordinata. Ma segue uno schema molto regolare. Allo stesso modo, potremmo esprimere la condizione su quattro colonne...

 (c1,c2,c3,c4) > (:lrv1,:lrv2,:lrv3,:lrv4)

Prendiamo solo quello che abbiamo per le tre colonne e dobbiamo espandere c3 > :lrv3 per sostituirlo con ( c3 >= :lrv3 AND ( c3 > :lrv3 OR c4 > :lrv4 ) )

 WHERE c1 >= :lrv1
       AND ( c1 > :lrv1 OR ( c2 >= :lrv2 
                             AND ( c2 > :lrv2 OR ( c3 >= :lrv3
                                                   AND ( c3 > :lrv3 OR c4 > :lrv4 )
                                                 )
                                 )
                           )
           )
 ORDER BY c1,c2,c3,c4
 LIMIT n

Come aiuto al futuro lettore, commenterei questo blocco, e indicherei l'intento...

 -- (c1,c2,c3,c4) > (lr1,lr2,lr3,lr4)

E sarebbe bello se MySQL ci permettesse di esprimere il confronto proprio così. Sfortunatamente, dobbiamo espanderlo in qualcosa che MySQL capisca.