2011-10-07 4 views
0

마침내 돌아오고 원하는 모든 것을 주문하는 큰 쿼리가 있습니다.MySQL LIMIT 및 OFFSET이 내 결과 주문을 엉망으로 만듭니다.

내 프로젝트에서 페이지 매김을 고집하고 있지만 이제는 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 

그래서 주문을하고

더 INFO-

내 테이블이의 일종 ADDED 미래에 가장 가까운 동물을 그룹화했습니다. 동물의 관련 날짜는 가장 가까운 날짜부터 오름차순까지, 가장 가까운 날짜부터 내림차순 순으로 정렬됩니다.

$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; 
    "; 
+2

같은 후 가진 코드 수 있습니다. – JohnFx

답변

1

LIMITOFFSET가 동일한 쿼리에 ORDER BY가없는 당신이 원하는 것을 일반적으로하지 않습니다. 샘플 코드에서 LIMIT은 하위 쿼리에 있고 해당 하위 쿼리의 레코드는 순서가 지정되어 있지 않습니다. 그래서 기본적으로 f3에서 임의의 5 행을 얻습니다.

아쉽게도이 문제를 처리하는 가장 좋은 방법은 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; 
+0

이 쿼리는 점점 더 복잡해지고 있습니다. 제한적이기 전에 주문해야하는 하위 쿼리 레코드가 무엇을 의미하는지 알고 있습니다. 좀 더 살펴 보겠습니다. 감사합니다. – penpen

+0

나는 지금 취업 인터뷰를하고 있는데,이 쿼리는 "Hunh? 왜 Postgres를 MySQL로 선호합니까?" –

+0

글쎄, MySQL은 내가 아는 전부지만, 내 지식을 넓히고 MariaDB를 살펴 보는 것부터 시작한다. Postgres를 많이 추천 해 주시겠습니까? 지금 가지고있는 데이터로 작동하는 솔루션에서 편집되었지만 일부 필드에 대해 걱정할 필요가 없습니다. 무작위로/가능한 성능 문제를 해결할 수 없습니다. – penpen

관련 문제