Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Paginacja MySQL oparta na kursorach z wieloma kolumnami

Jeśli (niestety nazwana) kolumna Column_1 jest wyjątkowy, możesz po prostu zrobić:

 WHERE Column_1 > :last_retrieved_value

Z pytania wynika, że ​​Column_1 nie jest unikalny, ale (Column_1,Column_2) krotka jest unikalna.

Ogólna forma zapytania „następna strona”, uporządkowana według tych dwóch kolumn, przy użyciu ostatnio pobranych wartości dla tych dwóch kolumn, wyglądałaby…

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

(lrv =wartość zapisana z ostatniego wiersza pobranego przez poprzednie zapytanie)

Aby napisać ten warunek w MySQL, możemy to zrobić tak, jak pokazano:

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

Albo moglibyśmy napisać to w ten sposób, co wolę, ponieważ jest znacznie mniejsza szansa, że ​​MySQL pomyli się z warunkiem OR i użyje niewłaściwego indeksu...

 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

Aby rozszerzyć to do trzech kolumn, aby sprawdzić stan...

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

Zajmujemy się tym podobnie jak w przypadku dwóch kolumn, obsługując c1 po pierwsze, rozbijając go tak, jak dwie kolumny:

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

A teraz ten symbol zastępczy ... (gdzie miałby tylko sprawdzić c2 wcześniej, to tak naprawdę kolejny przypadek dwóch kolumn. Musimy sprawdzić:(c2,c3) > (lrv2,lrv3) , więc możemy to rozwinąć za pomocą tego samego wzorca:

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

Zgadzam się, że rozszerzenie może wyglądać trochę niechlujnie. Ale postępuje zgodnie z bardzo regularnym wzorem. Podobnie możemy wyrazić warunek na czterech kolumny...

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

Po prostu bierzemy to, co mamy dla trzech kolumn i musimy rozwinąć c3 > :lrv3 aby zastąpić go ( 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

Jako pomoc przyszłemu czytelnikowi chciałbym skomentować ten blok i wskazać intencję ...

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

I fajnie by było, gdyby MySQL pozwolił nam w ten sposób wyrazić porównanie. Niestety, musimy rozszerzyć to na coś, co MySQL rozumie.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Relacja jeden-do-wielu w MySQL - jak zbudować model?

  2. Szukam odpowiednika dictcursor w flaskext.mysql

  3. Napraw Odmowa dostępu dla użytkownika 'root'@'localhost' dla phpMyAdmin

  4. Dlaczego nie powinieneś używać mysql_fetch_assoc więcej niż 1 raz?

  5. Eksportuj bazę danych MySQL za pomocą PHP