Search

626. Exchange Seats

-- beat 68% -- 서브쿼리가 많은 쿼리 SELECT CASE WHEN mod(id, 2) = 0 THEN id - 1 WHEN id = (SELECT MAX(id) FROM Seat) AND mod( (SELECT COUNT(*) FROM Seat), 2) != 0 THEN id -- 마지막 id이고 홀수일 때, ELSE id + 1 END as id, student FROM Seat ORDER BY id ASC ; +----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+---------------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+---------------------------------+ | 1 | PRIMARY | Seat | NULL | ALL | NULL | NULL | NULL | NULL | 5 | 100.00 | Using temporary; Using filesort | | 3 | SUBQUERY | Seat | NULL | index | NULL | PRIMARY | 4 | NULL | 5 | 100.00 | Using index | | 2 | SUBQUERY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Select tables optimized away | +----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+---------------------------------+ 3 rows in set, 1 warning (0.05 sec) -- type을 확인 -- 메인 쿼리가 전체 테이블 스캔(type이 'ALL')을 하고, 임시 테이블과 파일 정렬을 사용한다는 것 - 먼저 Seat를 Full scan -> temporary 영역을 이용하여 file sort 사용 - 서브쿼리 1: index scan -> primary key - 서브쿼리 2: 'Select tables optimized away' : 데이터베이스가 쿼리 최적화를 통해 실제 테이블 액세스 없이 결과를 도출했다는 것을 의미 -- 서브쿼리 최소화 -- 하지만 아래 쿼리는 leetcode에서는 지원 x SELECT COUNT(*) INTO @TotalCount FROM Seat; EXPLAIN SELECT CASE WHEN id % 2 = 0 THEN id - 1 WHEN id = @TotalCount THEN id ELSE id + 1 END as id, student FROM Seat ORDER BY id ASC; +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+ | 1 | SIMPLE | Seat | NULL | ALL | NULL | NULL | NULL | NULL | 5 | 100.00 | Using filesort | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+ 1 row in set, 1 warning (0.00 sec) -- case문 + window 함수 select id, student, lead(student, 1) over (order by id) as lead_student, lag(student, 1) over (order by id) as lag_student from Seat; +----+---------+--------------+-------------+ | id | student | lead_student | lag_student | +----+---------+--------------+-------------+ | 1 | Abbot | Doris | NULL | | 2 | Doris | Emerson | Abbot | | 3 | Emerson | Green | Doris | | 4 | Green | Jeames | Emerson | | 5 | Jeames | NULL > self | Green | +----+---------+--------------+-------------+ 5 rows in set (0.03 sec) -- 서브쿼리 최소화 -- Beats 96.74% -- case문 + window 함수 -- 홀수 일 경우에는 lead + null 값 대체 (자기 자신) -- 짝수 일 경우에는 lag -- 홀수 일 경우, 자기 앞의 id을 가져옴(id-1 과 같은 효과) -- coalesce(lead(student, 1) over(order by id), student) -- coalesce : 만약 제일 상단의 행일 경우, null이기 때문에 자기 자신으로 대체 -- 짝수일 경우 -- 자기 뒤의 id을 가져옴 (id + 1과 같은 효과) -- lag(student, 1) over(order by id) select id, case when id % 2 = 1 then coalesce( lead(student, 1) over(order by id), student ) else lag(student, 1) over(order by id) end as student from Seat; +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+ | 1 | SIMPLE | Seat | NULL | ALL | NULL | NULL | NULL | NULL | 5 | 100.00 | Using filesort | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+ 1 row in set, 2 warnings (0.02 sec) -- io를 줄인 것을 확인 -- filesort의 경우, window 함수로 인해 발생
SQL
복사
[..] 부분은 생략 가능하다. offset : 지정시 N번째 값을 가져온다. - default_value : N번째 값이 없을 경우 default_value값을 가져온다. PARTITION BY : 지정시 GROUP 별로 행 값을 가져온다. LEAD(<expr> [,offset[,default_value]]) OVER ([PARTITION BY <expr>] ORDER BY <expr>)
SQL
복사