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를 사용하지 않는 유일한 차이점은 중첩 된 선택에 의존합니다.