sql >> Base de Datos >  >> RDS >> Mysql

Paginación basada en cursor MySQL con múltiples columnas

Si (la lamentablemente nombrada) columna Column_1 es único, podrías simplemente hacer:

 WHERE Column_1 > :last_retrieved_value

De la pregunta, parece que Column_1 no es único, pero el (Column_1,Column_2) la tupla es única.

La forma general para una consulta de "página siguiente", ordenada por esas dos columnas, utilizando los últimos valores recuperados para esas dos columnas, sería...

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

(lrv =valor guardado de la última fila recuperada por la consulta anterior)

Para escribir esa condición en MySQL, podemos hacerlo como lo ha mostrado:

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

O bien, podríamos escribirlo así, lo cual prefiero, porque hay muchas menos posibilidades de que MySQL se confunda con la condición OR y use el índice incorrecto...

 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

Para extender eso a tres columnas, para comprobar la condición...

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

Lo manejamos como en el caso de dos columnas, manejando c1 primero, dividiéndolo como las dos columnas:

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

Y ahora ese marcador de posición ... (donde habría tenido solo el cheque en c2 antes, es realmente otra vez solo otro caso de dos columnas. Necesitamos comprobar:(c2,c3) > (lrv2,lrv3) , por lo que podemos expandir eso usando el mismo patrón:

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

Estoy de acuerdo en que la expansión puede parecer un poco desordenada. Pero sigue un patrón muy regular. De manera similar, podríamos expresar la condición en cuatro columnas...

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

Simplemente tomamos lo que tenemos para las tres columnas y necesitamos expandir c3 > :lrv3 para reemplazarlo 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

Como ayuda al futuro lector, comentaría este bloque e indicaría la intención...

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

Y sería bueno si MySQL nos permitiera expresar la comparación así. Desafortunadamente, tenemos que expandir eso a algo que MySQL entienda.