[mysql] MySQL의 ROW_NUMBER ()

MySQL에서 SQL Server 기능을 복제하는 좋은 방법이 ROW_NUMBER()있습니까?

예를 들면 다음과 같습니다.

SELECT 
    col1, col2, 
    ROW_NUMBER() OVER (PARTITION BY col1, col2 ORDER BY col3 DESC) AS intRow
FROM Table1

그런 다음 예를 들어 조건 intRow을 1로 제한 하여 col3(col1, col2)쌍 마다 가장 높은 단일 행을 얻을 수 있습니다.



답변

각 (col1, col2) 쌍마다 단일 최고 col3 행을 원합니다.

그것은 가장 일반적으로 묻는 SQL 질문 중 하나 인 그룹 별 최대 값입니다 (쉽게 보이지만 실제로는 그렇지 않기 때문에).

나는 종종 빈약 한 자조에 빠졌다.

SELECT t0.col3
FROM table AS t0
LEFT JOIN table AS t1 ON t0.col1=t1.col1 AND t0.col2=t1.col2 AND t1.col3>t0.col3
WHERE t1.col1 IS NULL;

“일치하는 col1을 가진 다른 행이없는 테이블의 행을 가져옵니다. (이것과 대부분의 다른 그룹 별 최대 솔루션은 하나 이상의 행에 동일한 col1, col2, col3이 있으면 여러 행을 반환합니다. 문제가 있으면 사후 처리가 필요할 수 있습니다.)


답변

MySQL에는 순위 기능이 없습니다. 가장 가까운 것은 변수를 사용하는 것입니다.

SELECT t.*, 
       @rownum := @rownum + 1 AS rank
  FROM YOUR_TABLE t, 
       (SELECT @rownum := 0) r

내 경우에는 어떻게 작동합니까? col1과 col2 각각에 하나씩 두 개의 변수가 필요합니까? col1이 변경되었을 때 Col2가 어떻게 든 재설정되어야합니까?

예. Oracle 인 경우 LEAD 함수를 사용하여 다음 값에서 정점에 도달 할 수 있습니다. 고맙게도, Quassnoi는 MySQL 구현에 필요한 로직을 다룹니다 .


답변

나는 항상이 패턴을 따릅니다. 이 테이블이 주어지면 :

+------+------+
|    i |    j |
+------+------+
|    1 |   11 |
|    1 |   12 |
|    1 |   13 |
|    2 |   21 |
|    2 |   22 |
|    2 |   23 |
|    3 |   31 |
|    3 |   32 |
|    3 |   33 |
|    4 |   14 |
+------+------+

이 결과를 얻을 수 있습니다 :

+------+------+------------+
|    i |    j | row_number |
+------+------+------------+
|    1 |   11 |          1 |
|    1 |   12 |          2 |
|    1 |   13 |          3 |
|    2 |   21 |          1 |
|    2 |   22 |          2 |
|    2 |   23 |          3 |
|    3 |   31 |          1 |
|    3 |   32 |          2 |
|    3 |   33 |          3 |
|    4 |   14 |          1 |
+------+------+------------+

이 쿼리를 실행하면 변수를 정의 할 필요가 없습니다.

SELECT a.i, a.j, count(*) as row_number FROM test a
JOIN test b ON a.i = b.i AND a.j >= b.j
GROUP BY a.i, a.j

희망이 도움이됩니다!


답변

SELECT
    @i:=@i+1 AS iterator,
    t.*
FROM
    tablename AS t,
    (SELECT @i:=0) AS foo


답변

이 기사에서 MySQL의 파티션으로 SQL ROW_NUMBER ()를 모방하는 방법을 보여줍니다. WordPress 구현 에서이 동일한 시나리오에 부딪 쳤습니다. ROW_NUMBER ()가 필요했지만 거기에 없었습니다.

http://www.explodybits.com/2011/11/mysql-row-number/

이 기사의 예제는 필드 별 단일 파티션을 사용하는 것입니다. 추가 필드로 파티션을 나누려면 다음과 같이 할 수 있습니다.

  SELECT  @row_num := IF(@prev_value=concat_ws('',t.col1,t.col2),@row_num+1,1) AS RowNumber
         ,t.col1
         ,t.col2
         ,t.Col3
         ,t.col4
         ,@prev_value := concat_ws('',t.col1,t.col2)
    FROM table1 t,
         (SELECT @row_num := 1) x,
         (SELECT @prev_value := '') y
   ORDER BY t.col1,t.col2,t.col3,t.col4 

concat_ws를 사용하면 null을 처리합니다. int, date 및 varchar을 사용하여 3 개의 필드에 대해 이것을 테스트했습니다. 도움이 되었기를 바랍니다. 이 쿼리를 분류하고 설명하는 기사를 확인하십시오.


답변

에서 MySQL 8.0.0이상 당신은 기본적으로 윈도우 기능을 사용할 수 있습니다.

1.4 MySQL 8.0의 새로운 기능 :

창 기능.

MySQL은 이제 쿼리의 각 행에 대해 해당 행과 관련된 행을 사용하여 계산을 수행하는 창 기능을 지원합니다. 여기에는 RANK (), LAG () 및 NTILE ()와 같은 함수가 포함됩니다. 또한 기존의 여러 집계 함수를 창 함수로 사용할 수 있습니다. 예를 들어 SUM () 및 AVG ()입니다.

ROW_NUMBER () over_clause :

파티션 내의 현재 행 번호를 반환합니다. 행 번호 범위는 1에서 파티션 행 수까지입니다.

ORDER BY는 행의 번호가 매겨지는 순서에 영향을줍니다. ORDER BY가 없으면 행 번호가 결정되지 않습니다.

데모:

CREATE TABLE Table1(
  id INT AUTO_INCREMENT PRIMARY KEY, col1 INT,col2 INT, col3 TEXT);

INSERT INTO Table1(col1, col2, col3)
VALUES (1,1,'a'),(1,1,'b'),(1,1,'c'),
       (2,1,'x'),(2,1,'y'),(2,2,'z');

SELECT
    col1, col2,col3,
    ROW_NUMBER() OVER (PARTITION BY col1, col2 ORDER BY col3 DESC) AS intRow
FROM Table1;

DBFiddle 데모


답변

또한 쿼리 코드를 약간 수정하여 Mosty Mostacho의 솔루션에 투표했습니다.

SELECT a.i, a.j, (
    SELECT count(*) from test b where a.j >= b.j AND a.i = b.i
) AS row_number FROM test a

동일한 결과를 얻을 것입니다 :

+------+------+------------+
|    i |    j | row_number |
+------+------+------------+
|    1 |   11 |          1 |
|    1 |   12 |          2 |
|    1 |   13 |          3 |
|    2 |   21 |          1 |
|    2 |   22 |          2 |
|    2 |   23 |          3 |
|    3 |   31 |          1 |
|    3 |   32 |          2 |
|    3 |   33 |          3 |
|    4 |   14 |          1 |
+------+------+------------+

테이블 :

+------+------+
|    i |    j |
+------+------+
|    1 |   11 |
|    1 |   12 |
|    1 |   13 |
|    2 |   21 |
|    2 |   22 |
|    2 |   23 |
|    3 |   31 |
|    3 |   32 |
|    3 |   33 |
|    4 |   14 |
+------+------+

쿼리에서 JOIN과 GROUP BY를 사용하지 않는 유일한 차이점은 중첩 된 선택에 의존합니다.