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이상 당신은 기본적으로 윈도우 기능을 사용할 수 있습니다.
창 기능.
MySQL은 이제 쿼리의 각 행에 대해 해당 행과 관련된 행을 사용하여 계산을 수행하는 창 기능을 지원합니다. 여기에는 RANK (), LAG () 및 NTILE ()와 같은 함수가 포함됩니다. 또한 기존의 여러 집계 함수를 창 함수로 사용할 수 있습니다. 예를 들어 SUM () 및 AVG ()입니다.
파티션 내의 현재 행 번호를 반환합니다. 행 번호 범위는 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;
답변
또한 쿼리 코드를 약간 수정하여 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를 사용하지 않는 유일한 차이점은 중첩 된 선택에 의존합니다.
