MySQL LIMIT и OFFSET портят мой порядок результатов - PullRequest
0 голосов
/ 07 октября 2011

У меня большой запрос, который наконец возвращает и упорядочивает все, что я хочу.

Я придерживаюсь нумерации страниц в своем проекте, однако теперь LIMIT и OFFSET в запросе, результаты упорядочены по-разному. Есть идеи?

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ-

Мои таблицы примерно такие:

ANIMAL                       FOOD
AID   AnimalName             FID   FoodName       BuyOn           AID
------------------            ------------------------------------------
 1       Dog                   1     DogBix         2011-11-27     1         
 2       Cat                   2     Tuna           2011-11-11     2
 3       Rabbit                3     Bones          2012-06-08     1
 4       Bird                  4     CatBix         2010-06-04     2  
                               5     Bird Seed      2011-12-12     4
                               6     Carrots        2011-05-04     3
                               7     Pedigree Chum  2011-02-08     1
                               8     Rabbit Mix     2011-09-02     3

И я хочу получить следующий вывод в следующем порядке:

AnimalName   FoodName       BuyOn
----------------------------------------
Cat          Tuna           2011-11-11
Cat          CatBix         2010-06-04

Dog          DogBix         2011-11-27
Dog          Bones          2012-06-08
Dog          Pedigree Chum  2011-02-08

Bird         Bird Seed      2011-12-12

Rabbit       Rabbit Mix     2011-09-02
Rabbit       Carrots        2011-05-04

Так упорядочено и сгруппировано по животным с ближайшей датой будущей даты. Даты, связанные с животным, упорядочиваются по дате, ближайшей к возрастающей, а затем по дате, ближайшей к убывающей.

У меня есть запрос:

$offset = ~whatever page I'm on * LIMIT~

$Query = "
  SELECT *
  FROM animal AS a
  INNER JOIN food AS f ON a.aid = f.fid
  INNER JOIN
  (
     SELECT f2.aid,
     MIN( IF( DATEDIFF( f2.buyOn, CURDATE() ) >= 0, DATEDIFF( f2.buyOn, CURDATE() ), 1000000 ) ) AS dateSortFuture,
     MAX( IF( DATEDIFF( f2.buyOn, CURDATE() ) < 0, DATEDIFF( f2.buyOn, CURDATE() ), -1000000 ) ) AS dateSortPast
     FROM food AS f2
     GROUP BY f2.aid
 LIMIT 5
 OFFSET ".$offset."
  )
  AS f3 ON f3.aid = a.aid
  ORDER BY f3.dateSortFuture ASC,
  f3.dateSortPast DESC,
  IF( f.buyOn >= CURDATE(), 0, 1 ) ASC,
  ABS( DATEDIFF( f.buyOn, CURDATE() ) ) ASC, animalName;";

С удаленными LIMIT и OFFSET все работает как я хочу.

ВОЗМОЖНОЕ РЕШЕНИЕ?:

$Query = "
  SELECT *
  FROM animal AS a
  INNER JOIN food AS f ON a.aid = f.fid
  INNER JOIN
  (
     SELECT f2.aid,
     MIN( IF( DATEDIFF( f2.buyOn, CURDATE() ) >= 0, DATEDIFF( f2.buyOn, CURDATE() ), 1000000 ) ) AS dateSortFuture,
     MAX( IF( DATEDIFF( f2.buyOn, CURDATE() ) < 0, DATEDIFF( f2.buyOn, CURDATE() ), -1000000 ) ) AS dateSortPast
     FROM food AS f2
     GROUP BY f2.aid
     ORDER BY f3.dateSortFuture ASC,
     f3.dateSortPast DESC,
     IF( f.buyOn >= CURDATE(), 0, 1 ) ASC,
     ABS( DATEDIFF( f.buyOn, CURDATE() ) ) ASC, animalName;
 LIMIT 5
 OFFSET ".$offset."
  )
  AS f3 ON f3.aid = a.aid
  ORDER BY f3.dateSortFuture ASC,
  f3.dateSortPast DESC,
  IF( f.buyOn >= CURDATE(), 0, 1 ) ASC,
  ABS( DATEDIFF( f.buyOn, CURDATE() ) ) ASC, animalName;
  ";

1 Ответ

1 голос
/ 08 октября 2011

LIMIT и OFFSET обычно не то, что вам нужно, если только в одном запросе нет ORDER BY. В вашем примере кода LIMIT находится в подзапросе, а записи в этом подзапросе неупорядочены. Таким образом, в основном, вы получаете случайные 5 строк из f3.

К сожалению, на сегодняшний день лучший способ, которым я знаю для обработки этого, является оконное управление, которое MySQL еще не поддерживает (AFAIK). Вы можете взломать что-то похожее с фрагментом вроде

(SELECT f9.*, (SELECT COUNT(*) FROM mytable as f99 
               WHERE f99.sortkey <= f9.sortkey) 
              AS rank
 FROM mytable AS f9) AS kludge

и затем с кодом вроде

SELECT /* lots */ FROM 
mytable join myothertable ON /* blah */
JOIN /* copy above fragment */
ON kludge.id = mytable.id AND rank<=5;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...