2017-10-31 1 views
1

종결 비율로 순위가 매겨진 직원 목록을 생성해야합니다.MySQL 5.7 주문이 임시 순위 열에 영향을주는 이유는 무엇입니까?

SET @cnt = 0; 
SET @percent = 2.0; 

SELECT 
    CASE 
     WHEN stats.close/(stats.open+stats.close) = @percent THEN @cnt 
     ELSE (@cnt := @cnt + 1) 
    END rank, 
    stats.employee, 
    stats.close, 
    stats.open, 
    (@percent := stats.close/(stats.open+stats.close)) percent 
     FROM stats 
       WHERE stats.date = CURDATE() 
        ORDER BY percent 

그것은

| Rank | Employee | Close | Open | Percent| 
|  1| Smith|  9|  1| 0.90| 
|  2| Jones|  75| 25| 0.75| 
|  3|  Zed|  1|  9| 0.10| 
|  3| Adams|  10| 90| 0.10| 

반환이 쿼리는 의도 된 목적으로 만 제대로 반환하지 않아야 것 같습니다 쿼리를 검토 한 후 작동 : 나는 다음과 같은 저장 프로 시저를 만들었습니다. 다음과 같은 이유입니다.

MySQL은 ORDER BY를 처리하기 전에 SELECT를 처리합니다. 따라서 MySQL은 데이터베이스에서 나오기로 결정한 순서대로 순위를 지정한 다음 결과 세트를 정렬한다고 가정합니다. 나는 이것을 다음과 같이 기대합니다 :

| Rank | Employee | Close | Open | Percent| 
|  3| Smith|  9|  1| 0.90| 
|  2| Jones|  75| 25| 0.75| 
|  4|  Zed|  1|  9| 0.10| 
|  1| Adams|  10| 90| 0.10| 

왜 이런 경우가 아닙니까?

+0

MySQL 스펙에서는 동일한 명령문에서 변수를 읽고 설정할 수 없습니다. Percona의 프로그래머는 특정 CASE 관용구가 현재 빌드의 코드를 기반으로 작동 함을 발견했습니다. 이것은 귀하의 문제 일 수도 있고 아닐 수도 있습니다 : [mcve]를 읽고 행동하십시오. – philipxy

답변

1

@variables를 임의의 순서로 사용하는 것은 엄격하게 말하기는 어렵지만 MySQL이 여전히 부족한 ("pre-release"에서 여전히 v8.x 용으로 계획된) 창 기능을 모방하는 일반적인 "해킹"입니다.

이 "해킹"은 ORDER BY가 SELECT (2 개의 별개 단계가 아닌)와 함께 처리되는 것에 의존하며 예상보다 더 통합되었습니다. 예 :

SELECT * 
FROM (SELECT CASE 
       WHEN stats.close/(stats.open + stats.close) = @percent THEN 
       @cnt 
       ELSE (@cnt := @cnt + 1) 
       end              rank, 
       stats.employee, 
       stats.close, 
       stats.open, 
       (@percent := stats.close/(stats.open + stats.close)) 
       percent 
     FROM stats 
     CROSS JOIN (@percent := 0 x, @cnt :=0 y) vars 
     WHERE stats.date = Curdate() 
     ORDER BY percent ASC) d 
ORDER BY percent DESC 

내부 순서 percent ASC는 외측 위해 먼저 가장 높은 퍼센트를 넣어, 낮은 퍼센트 값에서 시작 순위를 설정한다.

실제 문제는 select 절에서 왼쪽에서 오른쪽 (위에서 본 것처럼 위에서 아래로) 순서식이 보장되지 않는다는 것입니다. 따라서 @cnt를 계산하기위한 @percent의 비교가 작성된 SQL에 표시된 방식으로 수행되지 않을 수도 있습니다. 실제로 그것은 "대부분의 시간"에 작동하지만 그렇지 않을 수도 있습니다. () 창 기능을 가져 오십시오!)

+0

더 많은 조사를 한 후에 필자는 필자가 필요로하는 커서를 발견했습니다. 커서로 데이터를 선택한 다음 결과 세트를 반복하고 순위를 지정합니다. –

관련 문제