SELECT CONCAT(name, ' (', COALESCE(email, '이메일 없음'), ')') AS user_profile FROM Users;
Oracle
SELECT name || ' (' || COALESCE(email, '이메일 없음') || ')' AS user_profile FROM Users;-- 또는 SELECT CONCAT(CONCAT(name, ' ('), COALESCE(email, '이메일 없음') || ')') AS user_profile FROM Users;-- Oracle의 CONCAT은 두 개의 인자만 받을 수 있어 중첩 사용하거나 ||와 혼용합니다.
ROW_NUMBER(), RANK(), DENSE_RANK()는 MySQL과 Oracle 모두 동일하게 사용합니다.
ROW_NUMBER() OVER (PARTITION BY ... ORDER BY ...)
RANK() OVER (PARTITION BY ... ORDER BY ...)
DENSE_RANK() OVER (PARTITION BY ... ORDER BY ...)
PARTITION BY는 그룹화 기준을 설정하고, ORDER BY는 정렬 기준을 설정합니다.
ROW_NUMBER()는 각 행에 고유한 번호를 부여합니다.
RANK()는 동일한 값에 대해 동일한 순위를 부여하지만, 다음 순위는 건너뜁니다.
DENSE_RANK()는 동일한 값에 대해 동일한 순위를 부여하지만, 다음 순위는 건너뛰지 않습니다.
예시
사용자(Users)를 나이(age)가 많은 순으로 순위 매기기
SELECT name, age, ROW_NUMBER() OVER (ORDER BY age DESC) AS row_num, RANK() OVER (ORDER BY age DESC) AS rnk, DENSE_RANK() OVER (ORDER BY age DESC) AS dense_rnkFROM Users;
SUM() OVER (...), AVG() OVER (...) 등도 MySQL과 Oracle에서 동일하게 사용합니다.
이 함수들은 특정 그룹 내에서 집계된 값을 계산할 수 있습니다.
SUM(값) OVER (PARTITION BY ... ORDER BY ...)
PARTITION BY는 그룹화 기준을 설정하고, ORDER BY는 정렬 기준을 설정합니다.
ROWS BETWEEN 절을 사용하여 윈도우의 범위를 지정할 수 있습니다.
UNBOUNDED PRECEDING는 시작점, CURRENT ROW는 현재 행, UNBOUNDED FOLLOWING은 끝점을 의미합니다.
RANGE BETWEEN은 값의 범위를 지정합니다.
ROWS는 행의 개수를 기준으로 범위를 지정합니다.
예시
각 사용자의 주문(Orders)에 대해, 해당 사용자의 총 주문 금액과 함께 각 주문 정보 표시
SELECT O.id AS order_id, U.name AS user_name, O.product, O.amount, SUM(O.amount) OVER (PARTITION BY U.id) AS user_total_amountFROM Orders OJOIN Users U ON O.user_id = U.idORDER BY U.name, O.id;
LAG()와 LEAD() 함수도 MySQL과 Oracle에서 동일하게 사용합니다.
이 함수들은 현재 행을 기준으로 이전 또는 이후의 행 값을 가져오는 데 사용됩니다.
LAG(값, 오프셋, 기본값) OVER (PARTITION BY ... ORDER BY ...)
LEAD(값, 오프셋, 기본값) OVER (PARTITION BY ... ORDER BY ...)
PARTITION BY는 그룹화 기준을 설정하고, ORDER BY는 정렬 기준을 설정합니다.
오프셋은 몇 행 전/후의 값을 가져올지를 설정합니다. 기본값은 1입니다.
기본값은 해당 행이 없을 경우 반환할 값을 설정합니다. 기본값을 설정하지 않으면 NULL이 반환됩니다.
예시
각 주문에 대해, 해당 사용자의 바로 이전 주문일 가져오기
SELECT O.id AS order_id, U.name AS user_name, O.order_date, LAG(O.order_date, 1, NULL) OVER (PARTITION BY U.id ORDER BY O.order_date) AS previous_order_dateFROM Orders OJOIN Users U ON O.user_id = U.idORDER BY U.name, O.order_date;
SELECT order_date, YEAR(order_date) AS order_year, MONTH(order_date) AS order_month, DAYNAME(order_date) AS order_daynameFROM Orders;
Oracle
SELECT order_date, EXTRACT(YEAR FROM order_date) AS order_year, EXTRACT(MONTH FROM order_date) AS order_month, TO_CHAR(order_date, 'FMDay') AS order_dayname -- 'FM'은 앞뒤 공백 제거FROM Orders;