2014-10-09 2 views
3

PHP 페이지에서 파일 테이블을 쿼리하고 사용자가 페이지의 열을 클릭하여 제목, 날짜, 크기, 상태 및 사용자 업로드 이름순으로 정렬 할 수 있습니다. 그런 다음 각 파일을 클릭하여 별도의 플레이어 페이지에서 볼 수 있습니다.MySQL에서 다음/이전 행 찾기

플레이어에서 이전/다음 버튼을 만들어 이전 또는 다음 파일 으로 이동하려면 파일 페이지에서 주문하고 싶습니다. 즉, 위에 나열된 매개 변수 중 하나를 사용하여 결과를 정렬 할 수 있습니다. 날짜 같은 것을 들어

, 그것은 아주 간단 :

SELECT * FROM Files WHERE date > curdate ORDER BY date LIMIT 1 

그러나, 다른 매개 변수 중 일부는 나에게 문제의 원인이됩니다

  • 난의 이름과 같은 문자열을 처리 할 방법을 사용자를 업로드 하시겠습니까?

  • 정렬 된 열의 다음 항목이 같은 값을 갖는 상황을 어떻게 처리합니까? 예를 들어 status는 0에서 3 사이의 int이고 대부분의 파일의 상태는 0입니다. 파일 페이지의 상태별로 정렬하면 상태 0, 상태 1 등의 모든 파일이 나열됩니다. 따라서 현재 파일이 0 상태 파일의 중간에있는 경우 다음 상태도 0인지 여부를 어떻게 알 수 있습니까?

는 (PS I가이 주제에 대한 스레드를 많이하지만 내가 한 위의 특정 상황을 해결을 보지 못했다 알고있다.)

+0

비슷한 주제에 대해 많은 질문이 있습니다. 실제로 많은 답변이 필요합니다. 고유하지 않은 값으로 주문하는 주요 문제를 식별 할 수있었습니다. "트릭"은 고유 한 항목에 주문하는 것입니다. 먼저 "주요"항목 (사용자가 주문한 항목과 주문한 비밀 "부"항목)을 통해 고유 한 행 식별자를 얻습니다 "트릭"은 "마지막으로 본"행의 값을 "다음"행에서 시작하는 것입니다. 적절한 색인을 사용하면이 방법이 다른 인기있는 방법보다 효율적이 될 수 있습니다. – spencer7593

답변

3

Q를 : 어떻게의 이름과 같은 문자열을 처리 할 업로드하는 사용자?

A : 날짜와 숫자를 처리하는 것과 같은 방법입니다. 문자열은 "주문 가능"합니다.

Q : 정렬 된 열의 다음 항목이 같은 값을 갖는 상황을 어떻게 처리합니까?

A : 고유하지 않은 날짜의 중복 값을 처리하는 것과 같은 방법입니다. "주요"정렬 열 이외에 고유 한 또 다른 "부"정렬 열 또는 고유 한 "주요"및 "작은"조합이 필요합니다.

"마이너"정렬 순서로 사용할 수있는 nullable이 아닌 열에는 PRIMARY KEY 또는 UNIQUE KEY가있는 것이 가장 이상적입니다.

"트릭"은 주 및 보조 값을 "마지막으로 본"행에 저장하고 쿼리의 해당 정보를 사용하여 "다음"페이지를 가져 와서 목록의 현재 위치를 저장하는 것입니다. 마지막 행에서

WHERE t.major >= :last_seen_major 
     AND (t.major > :last_seen_major OR t.minor > :last_seen_minor) 
    ORDER BY t.major ASC, t.minor ASC 
    LIMIT 1 

(이 경우, 한), 당신은 그 동일한 쿼리에 사용할 수 있도록 얻기 위해, 주요 및 사소한 컬럼의 값을 저장 할거야 " 다음 "행.

최상의 쿼리 성능을 얻으려면 선도 열이 (major, minor) 인 색인이 필요합니다.,

SELECT f.* 
    FROM Files f 
WHERE f.date >= :last_seen_date 
    AND (f.date > :last_seen_date OR f.id > :last_seen_id) 
ORDER BY f.date ASC, f.id ASC 
LIMIT 1 

이 다른 열을 기준으로 주문하려면 뭔가 다른 조항에 의해 WHERE 및 ORDER에 f.date 교체 : 당신이 id 열이 가정 쿼리를 기반으로

는, 당신은 이런 식으로 뭔가를 할 것 , 예. f.name.


덜 성능이 좋은 대안

다른 정말 인기있는 방법은이 LIMIT 절에 "오프셋"을 사용하는 것입니다. 언뜻

,이 우아한 해결책이 될 것으로 보인다,하지만 몇 가지 문제를 가지고있다.

당신은 할 수 : 행이 범위에 삽입되어있는 경우

ORDER BY major ASC, minor ASC LIMIT 41,1 

를 "다음"행에 대해, 당신은 증가,이 방법으로 1

ORDER BY major ASC, minor ASC LIMIT 42,1 

하나 개의 문제에 의해 상쇄 이미 표시된 행이 있으면 "다음"쿼리는 동일한 행을 반환합니다. 왜냐하면 41 번째 행은 이제 42 번째 행이기 때문입니다. 누군가가 행을 삭제하면 "다음"쿼리는 행을 건너 뜁니다. 그리고 나는 내 "get the next row"기능에 그런 종류의 결함으로 살기를 원하지 않는다. 그리고이 방법은 여전히 ​​목록의 위치를 ​​추적해야하지만 실제로 행의 일부가 아닌 추가 오프셋을 전달해야합니다.

이 방법의 또 다른 문제는 데이터베이스가 다음을 주문하고 마지막으로 대형 세트와 성능 문제가 될 수있는 LIMIT 절을 적용, 행을 검색 할 수 있다는 것입니다.

+0

감사합니다. 매우 도움이되었습니다. . 솔직히 말해서, 바인딩 변수를 사용하는 방법에 대한 확신이 없기 때문에 콜론을 제거하고 변수의 현재 값을 참조 했으므로 테스트에서 문제가 없습니다. 내 코드는 다음과 같습니다. '선택 f. * FROM Files f 어디 f.date> = $ date AND (f.date> $ date 또는 f .id> $ file_id) ORDER BY f.date ASC, f.id ASC LIMIT 1' 이전 파일을 찾는 데는 사실상 똑같지 만 역순으로 정렬하고 내림차순으로 정렬합니다. – mwoods