본문 바로가기
SQL/코딩테스트

[leetcode / MySQL] 626. Exchange Seats

by Hi_heidi 2024. 2. 22.

문제

💡 Write a solution to swap the seat id of every two consecutive students. If the number of students is odd, the id of the last student is not swapped.

Return the result table ordered by id in ascending order.

 

테이블 형태

 

풀이

SELECT id
    , CASE WHEN id=(SELECT COUNT(*) FROM Seat) AND id%2=1 THEN student
           WHEN id%2=1 THEN LEAD(student, 1) OVER (ORDER BY id) 
           WHEN id%2=0 THEN LAG(student, 1) OVER(ORDER BY id) 
    END AS student
FROM Seat

 

해설

  • 연속하는 두 학생의 좌석 ID를 바꿔서 출력하되
  • 학생 수가 홀수이면 마지막 학생의 ID는 그대로 출력해야 한다
SELECT id
    , CASE # WHEN id=(SELECT COUNT(*) FROM Seat) AND id%2=1 THEN student
           WHEN id%2=1 THEN LEAD(student, 1) OVER (ORDER BY id) 
           WHEN id%2=0 THEN LAG(student, 1) OVER(ORDER BY id) 
    END AS student
FROM Seat
  • CASE문의 2번째, 3번째 WHEN부터 해설한다. 연속하는 두 학생의 좌석 ID를 바꿔서 출력한다는 것은 연속하는 좌석ID의 student를 바꿔서 출력한다는 것과 같다. id가 홀수일 때 직후 id의 student 이름을 당겨오고(LEAD), id가 짝수일 때 직전 id의 student 이름을 미는 것으로(LAG) 해결할 수 있다.
  • id를 2로 나눈 나머지가 1일 때 홀수로 판별할 수 있고, 이 경우 LEAD로 student 이름을 1개 당겨온다. 당겨온다의 기준은 id를 기준으로 오름차순 정렬했을 때로 한다
  • id를 2로 나눈 나머지가 0일 때 짝수로 판별할 수 있고, 이 경우 LAG로 직전 student 이름을 1개 민다. 민다의 기준은 역시 id를 기준으로 오름차순 정렬했을 때로 한다
SELECT id
    , CASE WHEN id=(SELECT COUNT(*) FROM Seat) AND id%2=1 THEN student
          # WHEN id%2=1 THEN LEAD(student, 1) OVER (ORDER BY id) 
          # WHEN id%2=0 THEN LAG(student, 1) OVER(ORDER BY id) 
    END AS student
FROM Seat
  • 이후 CASE문의 1번째 WHEN을 해설한다. 첫 번째 WHEN은 마지막 학생 여부, 홀/짝수 여부의 2가지 조건을 판단하는 WHEN이다. 마지막 학생의 ID는 짝수일 때 swapping해서 출력하고, 홀수일 때 그대로 출력해야 한다.
  • 먼저 마지막 학생 여부는 SELECT문 서브쿼리로 판단할 수 있다. 전체 데이터 개수를 센 값과 id가 동일하면 마지막 학생이다. 홀/짝수 여부는 id를 2로 나눈 나머지가 1이면 홀수임을 판별할 수 있다
  • 홀수이면서 마지막 학생이면 student 값을 그대로 출력시킨다
  • 만일 짝수이면서 마지막이면 첫 번째 WHEN을 통과하고 3번째 WHEN으로 가서 swapping되어 출력된다(첫번째 WHEN 조건을 충족하지 못하기 때문)
  • 이는 CASE문의 맨 처음에 위치해야 하는데, 마지막에 위치하면 앞선 WHEN문에서 홀수나 짝수라는 조건을 만족시켜 앞선 규칙에 따라 처리되기 때문이다.
  • 런타임 빠르기는 보통이다

 

다른 사람의 풀이

  • 윈도우 함수를 사용하지 않고 id를 swapping한 sdimon13의 풀이
SELECT CASE
           WHEN s.id % 2 <> 0 AND s.id = (SELECT COUNT(*) FROM Seat) THEN s.id
           WHEN s.id % 2 = 0 THEN s.id - 1
           ELSE
               s.id + 1
           END AS id,
       student
FROM Seat AS s
ORDER BY id
  • 이 사람은 홀/짝을 판별해 id값을 조정하는 방법으로 풀이했다. CASE문의 맨 처음은 나와 동일하게 마지막 학생인지, 홀수인지 여부를 판단하는 WHEN문으로 작성했고, 그 이후 id가 짝수일 때 id에서 -1하여 swapping했다. 이외의 경우(=홀수일 경우) 는 id에서 +1을 하는 ELSE로 처리하였다. 이후 id기준 ORDER BY하여 출력 데이터를 정렬해주었다. 훨씬 간단하고 쿼리 속도도 빠르다.