SQL 준비

WHERE

  • 비교 연산자

    • = , < , > , <= ex) where col = 10

    • 문자형과 비교시에는 WHERE CITY = 'Paris'와 같이 인용부호로 감싸주어야 함.

  • 부정 비교 연산자

    • !=, not 컬럼명 = ex) where col ≠ 10 , where not col = 10

  • SQL 연산자

    • BETWEEN A AND B : A와 B의 사이 where col between 1 and 10

    • LIKE '비교 문자열'

      • 비교 문자열을 포함

      • %는 문자열을 의미, '_'는 하나의 문자를 의미

      • ex) where col like '방탄%'

    • IN (리스트)

      • LIST 중 하나와 일치

      • where col in (1,3,5)

    • IS NULL

      • where col is null

  • 부정 SQL 연산자

    • NOT BETWEEN A AND B

      • A와 B의 사이가 아님

      • where col not between 1 and 10

    • NOT IN (LIST)

      • where col ot in (1,3,5)

    • IS NOT NULL

      • NULL 값이 아님

      • where col is not null

  • 논리 연산자

    • AND

      • 모든 조건이 TRUE여야 함

      • where col > 1 and col < 10

    • OR

      • 하나 이상의 조건이 TRUE여야 함

      • where col = 1 or col = 10

    • NOT

      • TRUE면 FALSE이고 FALSE이면 TRUE

GROUP BY, HAVING 절

  • 데이터를 GROUP BY를 통해 그룹별로 묶고

  • 집계 함수를 통해 그룹별로 집계 데이터를 도출할 수 있다.

    • COUNT(*) : 전체 ROW를 Count 하여 반환

    • COUNT(컬럼) : 컬럼값이 Null인 Row를 제외하고 Count하여 반환

    • COUNT(DISTINCT 컬럼) : 컬럼값이 Null이 아닌 Row에서 중복을 제거한 Count를 반환

    • SUM(컬럼) : 컬럼값들의 합계를 반환

    • AVG(컬럼) : 컬럼값들의 평균을 반환 , NULL인 데이터를 제외한 컬럼값들의 평균을 반환

    • MIN(컬럼) : 컬럼값들의 최솟값을 반환

    • MAX(컬럼) : 컬럼값들의 최댓값을 반환

  • 근데 집계 함수가 꼭 GROUP BY와 함께 쓰는 건 아니다.

    • GROUP BY 없이 사용할 때 : 전체에 대한 계산 SELECT AVG(TOTAL_AMOUNT) FROM ORDERS

  • GROUP BY를 사용할 때, SELECT 절에는 다음 두 종류의 것만 올 수 있습니다.

    1. GROUP BY 절에 사용된 컬럼 (예: INGREDIENT_TYPE)

    2. 집계 함수(Aggregate Function) (예: SUM(TOTAL_ORDER), COUNT(FLAVOR))

  • HAVING

    • HAVING 절은 GROUP BY 절을 사용할 때 WHERE 절처럼 사용하는 조건절

SELECT - 5

FROM - 1

WHERE - 2 -> 먼저 필터링

GROUP BY - 3

HAVING - 4 그룹화된 결과에 대해 조건 적용

ORDER BY - 6 최종 결과를 정렬

2021년 7월 한 달 동안의 판매 데이터를 상품 코드로 그룹핑해서 COUNT를 구하면 상품별 판매량이 나오는데 HAVING 절을 이용하면 한 달간 1000개 이상 팔린 상품만 출력할 수 있다.

SELECT PRODUCT_CODE, COUNT(ORDER_CNT) AS ORDER_CNT

FROM ORDER_PRODUCT

WHERE ORDER_DATE BETWEEN '20210701' AND '20210731'

GROUP BY PRODUCT_CODE

HAVING COUNT(ORDER_CNT) ≥ 1000;

JOIN

  • EQUI JOIN , EQUAL 조건으로

  • NON EQUI JOIN

STANDARD JOIN

  • Inner Join

  • SELECT A.컬럼1, A.컬럼2, B.컬럼1 FROM PRODUCT A INNER JOIN PRODUCT_REVIEW B ON A.PRODUCT_CODE = B.PRODUCT_CODE

  • OUTER JOIN

    • left outer join

      • SELECT A.컬럼1, A.컬럼2, B.컬럼1 FROM PRODUCT A LEFT OUTER JOIN PRODUCT_REVIEW B ON A.PRODUCT_CODE = B.PRODUCT_CODE

    • right outer join

  • full outer join

    • 왼쪽, 오른쪽 테이블 모두 출력되는 방식

서브 쿼리

SELECT 절 : 스칼라 서브쿼리 FROM 절 : 인라인 뷰 WHERE 절, HAVING 절 : 중첩 서브쿼리

  • 스칼라 서브 쿼리 : 컬럼 대신 사용되므로 반드시 하나의 값만을 반환해야 한다.

  • 인라인 뷰 : FROM 절 등 테이블명이 올 수 있는 위치에 사용 가능하다.

  • 중첩 서브 쿼리

    • WHERE 절과 HAVING 절에 사용할 수 있다.

      • 비연관 서브 쿼리 : 메인쿼리와 관계를 맺고 있지 않음

        • SELECT NAME, JOB, BIRTHDAY, AGENCY_CODE FROM ENTERTAINER WHERE AGENCY_CODE = ( SELECT AGENCY_CODE FROM AGENCY WHERE AGENCY_NAME 'EDAM엔터테인먼트');

      • 연관 서브 쿼리 : 메인쿼리와 관계를 맺고 있음

        • 음료별 가장 많은 주문수량을 가진 주문번호를 조회한다.

        • SELECT ORDER_NO, DRINK_CODE, ORDER_CNT FROM CAFE_ORDER A WHERE ORDER_CNT = (SELECT MAX(ORDER_CNT) FROM CAFE_ORDER B

집합 연산자

  • UNION ALL : 각 쿼리의 결과 집합의 합집합이다. 중복된 행도 그대로 출력됨

    • SELECT * FROM RUNNING_MAN UNION ALL SELECT * FROM INFINITE_CHALLENGE;

  • UNION : 각 쿼리의 결과 집합의 합집합. 중복된 행은 한 줄로 출력

    • SELECT * FROM RUNNING_MAN UNION SELECT * FROM INFINITE_CHALLENGE;

  • INTERSECT : 각 쿼리의 결과 집합의 교집합이다. 중복된 행은 한 줄로 출력됨

    • SELECT * FROM RUNNING_MAN INTERSECT SELECT * FROM INFINITE_CHALLENGE;

  • MINUS/EXCEPT : 앞에 있는 쿼리의 결과 집합에서 뒤에 있는 쿼리의 결과 집합을 뺀 차집합이다. 중복된 행은 한 줄로 출력된다.

    • SELECT * FROM RUNNING_MAN MINUS SELECT * FROM INFINITE_CHALLENGE;

OVER()는 "윈도우 함수(Window Functions)"를 정의하는 데 사용되는 핵심 구문입니다. 윈도우 함수는 GROUP BY처럼 행을 하나로 집계하여 축소하지 않고, 각 행은 그대로 유지하면서 특정 범위(윈도우)의 행들을 기준으로 계산한 값을 각 행에 추가해주는 함수입니다.

OVER()와 함께 사용되는 함수는 크게 세 가지 그룹으로 나눌 수 있습니다.

  1. 집계 함수 (Aggregate Functions)

SUM()이 여기에 속합니다. GROUP BY와 함께 쓰이는 대부분의 집계 함수를 OVER()와 함께 사용할 수 있습니다.

  • SUM(): 파티션(그룹) 내의 합계 또는 누적 합계

  • COUNT(): 파티션 내의 개수 또는 누적 개수

  • AVG(): 파티션 내의 평균 또는 누적 평균

  • MAX() / MIN(): 파티션 내의 최댓값/최솟값

예시: 각 직원의 급여와 함께, 해당 직원이 속한 부서의 전체 급여 합계를 함께 보고 싶을 때

결과 (예상):

GROUP BY를 썼다면 Sales와 Engineering 두 줄만 남았겠지만, OVER()를 쓰니 모든 직원 정보가 그대로 유지되면서 부서 총합이 옆에 붙었습니다.

  1. 순위 함수 (Ranking Functions)

파티션 내에서 각 행의 순위를 매길 때 사용합니다.

  • ROW_NUMBER(): 파티션 내에서 순서대로 고유한 번호를 매김 (1, 2, 3, 4)

  • RANK(): 순위를 매김. 동점자가 있으면 같은 순위를 부여하고 다음 순위는 건너뜀 (1, 2, 2, 4)

  • DENSE_RANK(): RANK()와 비슷하지만, 동점자 다음 순위를 건너뛰지 않음 (1, 2, 2, 3)

  • NTILE(n): 파티션 내의 데이터를 n개의 그룹으로 나누어 그룹 번호를 부여

예시: 부서별로 급여가 높은 순서대로 순위를 매기고 싶을 때

  1. 분석/오프셋 함수 (Analytic/Offset Functions)

파티션 내에서 현재 행을 기준으로 앞, 뒤, 또는 처음/마지막 행의 값을 가져올 때 사용합니다.

  • LAG(col, n, default): 현재 행보다 n번째 이전 행의 col 값을 가져옴

  • LEAD(col, n, default): 현재 행보다 n번째 다음 행의 col 값을 가져옴

  • FIRST_VALUE(col): 파티션 내의 첫 번째 행의 col 값을 가져옴

  • LAST_VALUE(col): 파티션 내의 마지막 행의 col 값을 가져옴

예시: 부서 내에서 바로 다음으로 급여를 많이 받는 사람과의 급여 차이를 보고 싶을 때

결론

OVER()SUM()에만 국한되지 않습니다.

OVER()는 SQL에서 데이터를 분석하고, 순위를 매기고, 행 간의 관계를 계산하는 등 매우 정교한 작업을 가능하게 하는 핵심적인 문법입니다. 시니어 개발자로서 이 기능을 잘 이해하고 활용하면 복잡한 쿼리를 훨씬 간결하고 효율적으로 작성할 수 있습니다.

Last updated