예시:
-- 평균 급여보다 많이 받는 직원 찾기
SELECT emp_name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
실전 예시:
-- 각 직원의 부서 평균 급여 비교
SELECT
emp_name,
salary,
(SELECT AVG(salary) FROM employees e2
WHERE e2.dept_id = e1.dept_id) as dept_avg
FROM employees e1;
-- 잘못된 예시
SELECT *
FROM employees
WHERE salary > (SELECT AVG(salary)
FROM employees
WHERE department_id = department_id);
-- 올바른 예시
SELECT *
FROM employees e1
WHERE salary > (SELECT AVG(salary)
FROM employees e2
WHERE e2.department_id = e1.department_id);
SELECT employee_id, name FROM current_employees
UNION
SELECT employee_id, name FROM retired_employees;
SELECT amount, 'Income' as type FROM income
UNION ALL
SELECT amount, 'Expense' as type FROM expenses;
-- 양쪽 부서에 다 있는 직원 찾기
SELECT emp_id FROM dept_a
INTERSECT
SELECT emp_id FROM dept_b;
-- A 부서에만 있는 직원 찾기
SELECT emp_id FROM dept_a
MINUS
SELECT emp_id FROM dept_b;
-- 주문이 있는 고객만 찾기
SELECT customer_name
FROM customers c
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.customer_id = c.customer_id
);
-- 주문이 없는 고객 찾기
SELECT customer_name
FROM customers c
WHERE NOT EXISTS (
SELECT 1
FROM orders o
WHERE o.customer_id = c.customer_id
);
-- 부서/직급별 급여 합계와 전체 합계
SELECT dept_id, job_grade, SUM(salary)
FROM employees
GROUP BY ROLLUP(dept_id, job_grade);
-- 모든 조합의 매출 집계
SELECT region, product, SUM(sales)
FROM sales_data
GROUP BY CUBE(region, product);
-- 부서별, 직급별 각각의 집계
SELECT dept_id, job_grade, SUM(salary)
FROM employees
GROUP BY GROUPING SETS(dept_id, job_grade);
-- 부서별 급여 합계
SELECT dept_id, SUM(salary) as total_salary
FROM employees
GROUP BY dept_id;
-- 날짜별 누적 매출
SELECT
sale_date,
amount,
SUM(amount) OVER (
ORDER BY sale_date
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) as cumulative_sum
FROM sales;
SELECT
emp_name,
salary,
RANK() OVER (ORDER BY salary DESC) as salary_rank
FROM employees;
SELECT
emp_name,
salary,
DENSE_RANK() OVER (ORDER BY salary DESC) as dense_salary_rank
FROM employees;
SELECT
emp_name,
salary,
PERCENT_RANK() OVER (ORDER BY salary) * 100 as percentile
FROM employees;
-- 상위 5명만 가져오기
SELECT *
FROM employees
WHERE ROWNUM <= 5;
-- 급여 상위 5명
SELECT *
FROM (
SELECT *
FROM employees
ORDER BY salary DESC
)
WHERE ROWNUM <= 5;
-- 상위 5명과 동일 급여 받는 사람들까지
SELECT TOP 5 WITH TIES *
FROM employees
ORDER BY salary DESC;
-- 10개 건너뛰고 다음 5개 가져오기
SELECT *
FROM employees
ORDER BY emp_id
OFFSET 10 ROWS
FETCH NEXT 5 ROWS ONLY;
-- 페이지당 20개씩, 3번째 페이지
SELECT *
FROM products
ORDER BY product_id
OFFSET 40 ROWS
FETCH NEXT 20 ROWS ONLY;
-- 조직도 구조 조회
SELECT
LEVEL,
LPAD(' ', 2*(LEVEL-1)) || emp_name as hierarchy,
emp_id,
manager_id
FROM employees
START WITH manager_id IS NULL
CONNECT BY PRIOR emp_id = manager_id;
-- 부서별 통계를 임시로 만들어서 사용
WITH dept_stats AS (
SELECT
dept_id,
AVG(salary) as avg_salary,
COUNT(*) as emp_count
FROM employees
GROUP BY dept_id
)
SELECT * FROM dept_stats WHERE emp_count > 10;
-- 1부터 10까지의 숫자 생성
WITH RECURSIVE numbers(n) AS (
SELECT 1
UNION ALL
SELECT n + 1 FROM numbers WHERE n < 10
)
SELECT * FROM numbers;
-- 분기별 매출 피벗
SELECT *
FROM (
SELECT
product_category,
quarter,
sales_amount
FROM sales
)
PIVOT (
SUM(sales_amount)
FOR quarter IN (
'Q1' as Q1_SALES,
'Q2' as Q2_SALES,
'Q3' as Q3_SALES,
'Q4' as Q4_SALES
)
);
-- 분기별 매출 데이터를 행으로 변환
SELECT *
FROM quarterly_sales
UNPIVOT (
amount
FOR quarter IN (
Q1_AMOUNT as 'Q1',
Q2_AMOUNT as 'Q2',
Q3_AMOUNT as 'Q3',
Q4_AMOUNT as 'Q4'
)
);
-- 이메일에서 사용자명만 추출
SELECT REGEXP_SUBSTR(email, '^[^@]+') FROM users;
-- 전화번호에서 지역번호 추출
SELECT REGEXP_SUBSTR(phone, '^\d{2,3}') FROM contacts;
-- URL에서 도메인 추출
SELECT REGEXP_SUBSTR(url, 'https?://([^/]+)') FROM websites;
-- 문장에서 숫자만 추출
SELECT REGEXP_SUBSTR(
'The price is $123.45',
'\d+(\.\d+)?'
) FROM dual;
-- HTML 태그 제거
SELECT REGEXP_REPLACE(
'<p>Some text</p>',
'<[^>]+>',
''
) FROM dual;