1,2/ 3,4 / 5,6 이런 식으로 레코드들을 묶어서 그룹으로 만들려면?
ROW_NUMBER()는 써야 될 것 같고CEIL( (ROW_NUMBER() OVER(ORDER BY id)) / 2 )같은 그룹 내에서 swap을 하려면?
-- swap?
WITH cte as (SELECT id, student,
CEIL( (ROW_NUMBER() OVER(ORDER BY id)) / 2) as group_num,
ROW_NUMBER() OVER(ORDER BY id) as num
FROM Seat)
SELECT *
FROM cte
ORDER BY
group_num, id DESC
여기에서 ROW_NUMBER() OVER(ORDER BY id) as num으로 한 이유가
group_num, id로 정렬한 거랑은 별개로 1,2,3,4,5로 유지되는 컬럼을 갖기 위해서였는데 위와 같이 사용하면 id 옆에 같은 값으로 num이 새겨지는 것 밖에 안 된다.
| id | student | group_num | num |
|---|---|---|---|
| 2 | Doris | 1 | 2 |
| 1 | Abbot | 1 | 1 |
| 4 | Green | 2 | 4 |
| 3 | Emerson | 2 | 3 |
| 5 | Jeames | 3 | 5 |
이렇게 나온다.
-- swap?
WITH cte as (SELECT id, student,
CEIL( (ROW_NUMBER() OVER(ORDER BY id)) / 2) as group_num
FROM Seat)
SELECT id, student, group_num,
ROW_NUMBER() OVER(ORDER BY group_num, id DESC) as num
FROM cte
ORDER BY
group_num, id DESC
window function을 사용할 때, 새로 정렬한 순서에 맞게 다시 번호를 매기고 싶다면 window function 내 정렬과 테이블의 정렬을 같도록 해야 한다.
| id | student | group_num | num |
|---|---|---|---|
| 2 | Doris | 1 | 1 |
| 1 | Abbot | 1 | 2 |
| 4 | Green | 2 | 3 |
| 3 | Emerson | 2 | 4 |
| 5 | Jeames | 3 | 5 |
num 컬럼을 보면 제대로 정렬된 것을 볼 수 있다.
WITH cte as (SELECT id, student,
CEIL( (ROW_NUMBER() OVER(ORDER BY id)) / 2) as group_num
FROM Seat)
SELECT
ROW_NUMBER() OVER(ORDER BY group_num, id DESC) as id, student
FROM cte
ORDER BY
group_num, id DESC
근데 또 이렇게 하면
| id | student |
|---|---|
| 2 | Abbot |
| 1 | Doris |
| 4 | Emerson |
| 3 | Green |
| 5 | Jeames |
이렇게 나온다. 이건 쿼리문을 작성하다가 흔하게 할 수 있는 잘못인데,
위에서 작성한 대로 쿼리문을 그대로 사용하면서 별칭을 바꿨는데 ORDER BY group_num, id DESC가 그대로 남아있으면서 의도치 않은 재정렬이 되어버린 것이다.
WITH cte as (SELECT id, student,
CEIL( (ROW_NUMBER() OVER(ORDER BY id)) / 2) as group_num
FROM Seat)
SELECT
ROW_NUMBER() OVER(ORDER BY group_num, id DESC) as id, student
FROM cte
가장 편한 풀이는 그냥 CASE WHEN 사용해서 짝수일 때는 id - 1 하고 홀수일 때는 id + 1 한 다음에 id로 정렬하면 된다.