sql >> Database >  >> RDS >> Mysql

Op MySQL-cursor gebaseerde paginering met meerdere kolommen

Als (de helaas genoemde) kolom Column_1 is uniek, je zou gewoon kunnen doen:

 WHERE Column_1 > :last_retrieved_value

Uit de vraag blijkt dat Column_1 is niet uniek, maar de (Column_1,Column_2) tuple is uniek.

De algemene vorm voor een "volgende pagina"-query, geordend op die twee kolommen, waarbij de laatst opgehaalde waarden voor die twee kolommen worden gebruikt, zou zijn...

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

(lrv =waarde opgeslagen van de laatste rij die is opgehaald door de vorige zoekopdracht)

Om die voorwaarde in MySQL te schrijven, kunnen we dat doen zoals je hebt laten zien:

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

Of we kunnen het zo schrijven, wat mijn voorkeur heeft, omdat MySQL veel minder kans heeft om in de war te raken door de OR-voorwaarde en de verkeerde index te gebruiken...

 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

Om dat uit te breiden tot drie kolommen, om de voorwaarde te controleren...

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

We behandelen het net als in het geval van twee kolommen, met c1 eerst uitsplitsen, net als de twee kolommen:

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

En nu die tijdelijke aanduiding ... (waar zou alleen de controle op c2 zijn geweest voorheen, is eigenlijk weer gewoon een ander geval van twee kolommen. We moeten controleren:(c2,c3) > (lrv2,lrv3) , zodat we dat kunnen uitbreiden met hetzelfde patroon:

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

Ik ben het ermee eens dat de uitbreiding er misschien een beetje rommelig uitziet. Maar het volgt wel een heel regelmatig patroon. Op dezelfde manier kunnen we de voorwaarde uitdrukken op vier kolommen...

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

We nemen gewoon wat we hebben voor de drie kolommen, en we moeten c3 > :lrv3 uitbreiden om het te vervangen door ( 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

Als hulpmiddel voor de toekomstige lezer zou ik commentaar geven op dit blok en de bedoeling aangeven ...

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

En het zou mooi zijn als MySQL ons in staat zou stellen om de vergelijking zomaar uit te drukken. Helaas moeten we dat uitbreiden naar iets dat MySQL begrijpt.




  1. Hoe kan ik SQL schrijven voor een tabel die dezelfde naam heeft als een beveiligd sleutelwoord in MySql?

  2. SQLite FULL OUTER JOIN-emulatie

  3. Eclipse - voeg .jar toe aan Dynamic Web Project

  4. Functies van PostgreSQL-back-upmethode in AWS S3