sql >> Databasteknik >  >> RDS >> Mysql

MySQL-markörbaserad paginering med flera kolumner

If (den olyckligtvis namngivna) kolumnen Column_1 är unik, kan du bara göra:

 WHERE Column_1 > :last_retrieved_value

Av frågan framgår det att Column_1 är inte unik, men (Column_1,Column_2) tupel är unik.

Det allmänna formuläret för en "nästa sida"-fråga, sorterad efter dessa två kolumner, med de senast hämtade värdena för dessa två kolumner, skulle vara...

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

(lrv =värde sparat från den sista raden som hämtades av föregående fråga)

För att skriva det villkoret i MySQL kan vi göra det som du har visat:

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

Eller så kan vi skriva det så här, vilket jag föredrar, eftersom det är mycket mindre chans för MySQL att bli förvirrad av OR-villkoret och använda fel index...

 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

För att utöka det till tre kolumner för att kontrollera villkoret...

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

Vi hanterar det precis som i fallet med två kolumner, hanterar c1 först, dela ut det precis som de två kolumnerna:

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

Och nu den där platshållaren ... (där skulle bara ha haft kontroll på c2 innan, är egentligen återigen bara ett annat fall av två kolumner. Vi måste kontrollera:(c2,c3) > (lrv2,lrv3) , så att vi kan utöka det med samma mönster:

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

Jag håller med om att expansionen kan se lite rörig ut. Men det följer ett väldigt regelbundet mönster. På liknande sätt skulle vi kunna uttrycka villkoret på fyra kolumner...

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

Vi tar bara vad vi har för de tre kolumnerna, och vi behöver expandera c3 > :lrv3 för att ersätta den med ( 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

Som en hjälp för den framtida läsaren skulle jag kommentera detta block och ange avsikten ...

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

Och det skulle vara trevligt om MySQL skulle tillåta oss att uttrycka jämförelsen precis så. Tyvärr måste vi utöka det till något som MySQL förstår.




  1. REPLACE() Funktion i Oracle

  2. Hur man jämför datum i SQL

  3. Vad är det optimala MYSQL-frågenumret i php-skript?

  4. SQL Server-utlösare:DML-utlösare