본문 바로가기
프로그래밍/SQL, Hive, SAS 관련 정보

[SQL 기초] Query 작성/실행 순서

by TrillionNT 2024. 10. 31.

2025.02.24 - [프로그래밍/SQL, Hive, SAS 관련 정보] - [SQL] Table of Contents


SQL의 작성 순서실행 순서는 다릅니다. SQL 쿼리를 작성할 때는 일반적으로 우리가 이해하기 쉬운 순서로 작성하지만, 데이터베이스 엔진은 최적화 및 효율성을 위해 다른 순서로 실행합니다. 작성 순서와 실행 순서를 비교하면 SQL 쿼리가 어떻게 처리되는지 이해하는 데 도움이 됩니다.
 

1. Query 작성 순서

  • SELECT - 조회할 컬럼을 지정합니다.
  • FROM - 데이터를 가져올 테이블을 지정합니다.
  • JOIN - 필요한 경우 테이블을 결합합니다.
  • WHERE - 조건을 지정하여 데이터를 필터링합니다.
  • GROUP BY - 그룹화할 기준을 지정합니다.
  • HAVING - 그룹화된 데이터에 조건을 적용합니다.
  • ORDER BY - 데이터를 정렬합니다.
  • LIMIT 또는 OFFSET - 결과의 개수를 제한하거나 특정 위치부터 데이터를 가져옵니다.

 

2. Query 실행 순서

  • FROM - 데이터를 조회할 테이블 결정
  • WHERE - 조건을 만족하는 행을 필터링
  • GROUP BY - 특정 컬럼을 기준으로 그룹화
  • HAVING - 그룹화된 결과에 대한 필터링
  • SELECT - 최종적으로 필요한 컬럼 선택
  • ORDER BY - 정렬 수행
  • LIMIT -  결과 개수 제한

예시를 통해서 살펴볼까요?

SELECT department, COUNT(employee_id) AS employee_count
FROM employees
JOIN departments ON employees.department_id = departments.id
WHERE salary > 50000
GROUP BY department
HAVING COUNT(employee_id) > 5
ORDER BY employee_count DESC
LIMIT 3;

 
 
 
이 쿼리는 다음 순서로 실행됩니다:

  1. FROM employees - employees 테이블에서 데이터를 불러옵니다.
  2. JOIN departments - employees와 departments 테이블을 department_id를 기준으로 결합합니다.
  3. WHERE salary > 50000 - salary가 50000보다 큰 데이터만 필터링합니다.
  4. GROUP BY department - department별로 그룹화합니다.
  5. HAVING COUNT(employee_id) > 5 - 각 department에서 직원 수가 5명 이상인 경우만 남깁니다.
  6. SELECT department, COUNT(employee_id) AS employee_count - department와 직원 수(employee_count)를 선택합니다.
  7. ORDER BY employee_count DESC - 직원 수를 기준으로 내림차순으로 정렬합니다.
  8. LIMIT 3 - 상위 3개의 행만 가져옵니다.

 

 


연산자 우선순위 때문에 에러가 발생하는 코드 예시를 보시죠.

https://leetcode.com/problems/consecutive-numbers/?envType=study-plan-v2&envId=top-sql-50

 

연산자 우선순위를 고려하지 않고 코드를 짰더니 

select distinct(num) ConsecuriveNums
from Logs
where (num=(lag(num, 1) over())) and (num=(lag(num, 2) over()))

 

에러가 발생합니다. SQL 쿼리는 일반적으로 FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY 순으로 처리됩니다. 윈도우 함수는 SELECT 단계에서 계산됩니다. 즉, WHERE 절에서 행을 필터링할 때는 아직 윈도우 함수 결과가 계산되기 전이기 때문에 사용할 수 없습니다.

그러니까 제대로 작동하기 위해서는 아래와 같이 Sub-query를 써 줘야 합니다. 

select distinct(num) ConsecutiveNums
from 
    (select id, num, lag(num, 1) over() l1, lag(num, 2) over() l2
    from Logs) tt
where num=l1 and num=l2