반응형
반응형

1. 분석 함수(Analytic Function)

  • 분석 함수란?

    • 테이블의 행을 특정 그룹별로 그루핑하여 편리하게 함수를 적용하는 것
  • Sample 데이터 생성 SQL

-- 1. PRODUCT_GROUP 테이블 생성
CREATE TABLE PRODUCT_GROUP (
GROUP_ID SERIAL PRIMARY KEY,
GROUP_NAME VARCHAR (255) NOT NULL
);

-- 1.1 PRODUCT_GROUP 데이터 삽입
INSERT INTO PRODUCT_GROUP (GROUP_NAME)
VALUES
('Smartphone')
, ('Laptop')
, ('Tablet');

SELECT * FROM PRODUCT_GROUP

group_id group_name
0 1 Smartphone
1 2 Laptop
2 3 Tablet
-- 2. PRODUCT 테이블 생성
CREATE TABLE PRODUCT (
PRODUCT_ID SERIAL PRIMARY KEY
, PRODUCT_NAME VARCHAR (255) NOT NULL
, PRICE DECIMAL (11, 2)
, GROUP_ID INT NOT NULL
, FOREIGN KEY (GROUP_ID)
REFERENCES PRODUCT_GROUP (GROUP_ID)
);

-- 2.1 PRODUCT 데이터 삽입
INSERT INTO PRODUCT (PRODUCT_NAME,
GROUP_ID,PRICE)
VALUES
('Microsoft Lumia', 1, 200)
, ('HTC One', 1, 400)
, ('Nexus', 1, 500)
, ('iPhone', 1, 900)
, ('HP Elite', 2, 1200)
, ('Lenovo Thinkpad', 2, 700)
, ('Sony VAIO', 2, 700)
, ('Dell Vostro', 2, 800)
, ('iPad', 3, 700)
, ('Kindle Fire', 3, 150)
, ('Samsung Galaxy Tab', 3, 200);

SELECT * FROM PRODUCT

product_id product_name price group_id
0 1 Microsoft Lumia 200 1
1 2 HTC One 400 1
2 3 Nexus 500 1
3 4 iPhone 900 1
4 5 HP Elite 1200 2
5 6 Lenovo Thinkpad 700 2
6 7 Sony VAIO 700 2
7 8 Dell Vostro 800 2
8 9 iPad 700 3
9 10 Kindle Fire 150 3
10 11 Samsung Galaxy Tab 200 3

2. OVER절

  • OVER절?
    • GROUP BY의 한계를 개선하기 위해 나온 함수
    • 집계 함수의 결과를 테이블에 바로 보여줌
SELECT *
      , COUNT(*) OVER()
FROM PRODUCT

product_id product_name price group_id count
0 1 Microsoft Lumia 200 1 11
1 2 HTC One 400 1 11
2 3 Nexus 500 1 11
3 4 iPhone 900 1 11
4 5 HP Elite 1200 2 11
5 6 Lenovo Thinkpad 700 2 11
6 7 Sony VAIO 700 2 11
7 8 Dell Vostro 800 2 11
8 9 iPad 700 3 11
9 10 Kindle Fire 150 3 11
10 11 Samsung Galaxy Tab 200 3 11

3. OVER ... PARTITION BY 절

  • PARTITION BY 절?
    • GROUP BY와 비슷한 기능으로 OVER절, 분석함수와 같이 사용
    • 특정 칼럼으로 그룹핑 하여 앞의 집계 함수를 그룹별로 적용
SELECT
    A.PRODUCT_NAME
    , A.PRICE
    , B.GROUP_NAME
    , AVG (A.PRICE) OVER (PARTITION BY B.GROUP_NAME)
FROM
PRODUCT A
INNER JOIN PRODUCT_GROUP B
ON (A.GROUP_ID = B.GROUP_ID);

product_name price group_name avg
0 HP Elite 1200 Laptop 850
1 Lenovo Thinkpad 700 Laptop 850
2 Sony VAIO 700 Laptop 850
3 Dell Vostro 800 Laptop 850
4 Microsoft Lumia 200 Smartphone 500
5 HTC One 400 Smartphone 500
6 Nexus 500 Smartphone 500
7 iPhone 900 Smartphone 500
8 iPad 700 Tablet 350
9 Kindle Fire 150 Tablet 350
10 Samsung Galaxy Tab 200 Tablet 350

4. ROW _NUMBER, RANK, DENSE_RANK 함수

  • 그룹에서 특정 컬럼의 순위를 구하는 함수

    함수명 내용
    ROW_NUMBER - 같은 순위면 중복 상관 없이 순서대로 순위 구함
    - EX) 10,20,20,30 일 때 -> 순위 : 1,2,3,4
    RANK - 같은 순위면 다음 순위로 건너뜀
    - EX) 10,20,20,30 일 때 -> 순위 : 1,2,2,4
    DENSE_RANK - 같은 순위면 다음 순위로 건너뛰지 않음
    -EX) 10,20,20,30 일 때 -> 순위 : 1,1,2,3
  • ROW_NUMBER

SELECT
    A.PRODUCT_NAME
    , B.GROUP_NAME
    , A.PRICE
    , ROW_NUMBER () OVER ( PARTITION BY B.GROUP_NAME ORDER BY A.PRICE)
FROM PRODUCT A
INNER JOIN PRODUCT_GROUP B
ON (A.GROUP_ID = B.GROUP_ID);

product_name group_name price row_number
0 Sony VAIO Laptop 700 1
1 Lenovo Thinkpad Laptop 700 2
2 Dell Vostro Laptop 800 3
3 HP Elite Laptop 1200 4
4 Microsoft Lumia Smartphone 200 1
5 HTC One Smartphone 400 2
6 Nexus Smartphone 500 3
7 iPhone Smartphone 900 4
8 Kindle Fire Tablet 150 1
9 Samsung Galaxy Tab Tablet 200 2
10 iPad Tablet 700 3
  • RANK
SELECT
    A.PRODUCT_NAME
    , B.GROUP_NAME
    , A.PRICE
    , RANK () OVER ( PARTITION BY B.GROUP_NAME ORDER BY A.PRICE)
FROM PRODUCT A
INNER JOIN PRODUCT_GROUP B
ON (A.GROUP_ID = B.GROUP_ID);

product_name group_name price rank
0 Sony VAIO Laptop 700 1
1 Lenovo Thinkpad Laptop 700 1
2 Dell Vostro Laptop 800 3
3 HP Elite Laptop 1200 4
4 Microsoft Lumia Smartphone 200 1
5 HTC One Smartphone 400 2
6 Nexus Smartphone 500 3
7 iPhone Smartphone 900 4
8 Kindle Fire Tablet 150 1
9 Samsung Galaxy Tab Tablet 200 2
10 iPad Tablet 700 3
  • DENSE_RANK
SELECT
    A.PRODUCT_NAME
    , B.GROUP_NAME
    , A.PRICE
    , DENSE_RANK () OVER ( PARTITION BY B.GROUP_NAME ORDER BY A.PRICE)
FROM PRODUCT A
INNER JOIN PRODUCT_GROUP B
ON (A.GROUP_ID = B.GROUP_ID);

product_name group_name price dense_rank
0 Sony VAIO Laptop 700 1
1 Lenovo Thinkpad Laptop 700 1
2 Dell Vostro Laptop 800 2
3 HP Elite Laptop 1200 3
4 Microsoft Lumia Smartphone 200 1
5 HTC One Smartphone 400 2
6 Nexus Smartphone 500 3
7 iPhone Smartphone 900 4
8 Kindle Fire Tablet 150 1
9 Samsung Galaxy Tab Tablet 200 2
10 iPad Tablet 700 3

5. FIRST _VALUE , LAST_VALUE 함수

  • 그룹안에서 특정컬럼의 첫 번째 값 또는 마지막 값을 구하는 함수

  • FIRST_VALUE(컬럼명)

    • 그룹안에서 컬럼명의 첫 번째 값을 구함
SELECT
  A.PRODUCT_NAME, B.GROUP_NAME, A.PRICE
  , FIRST_VALUE (A.PRICE) over (
      PARTITION BY B.GROUP_NAME ORDER BY A.PRICE
      ) AS LOWEST_PRICE_PER_GROUP
FROM PRODUCT A
INNER JOIN PRODUCT_GROUP B
ON (A.GROUP_ID = B.GROUP_ID);

product_name group_name price lowest_price_per_group
0 Sony VAIO Laptop 700 700
1 Lenovo Thinkpad Laptop 700 700
2 Dell Vostro Laptop 800 700
3 HP Elite Laptop 1200 700
4 Microsoft Lumia Smartphone 200 200
5 HTC One Smartphone 400 200
6 Nexus Smartphone 500 200
7 iPhone Smartphone 900 200
8 Kindle Fire Tablet 150 150
9 Samsung Galaxy Tab Tablet 200 150
10 iPad Tablet 700 150
  • LAST_VALUE(컬럼명)

    • 그룹안에서 컬럼명의 마지막 값을 구함

    • 범위 지정 옵션 : 옵션 범위 기준 마지막값을 구함

      옵션 내용
      RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING 첫 번째 로우부터 마지막 로우
      RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 첫 번째 로우부터 현재 로우
SELECT
  A.PRODUCT_NAME, B.GROUP_NAME, A.PRICE
  , LAST_VALUE (A.PRICE) OVER(
    PARTITION BY B.GROUP_NAME ORDER BY A.PRICE
    RANGE BETWEEN UNBOUNDED PRECEDING
    AND UNBOUNDED FOLLOWING
  ) AS HIGHEST_PRICE_PER_GROUP
FROM PRODUCT A
INNER JOIN PRODUCT_GROUP B
ON (A.GROUP_ID = B.GROUP_ID);

product_name group_name price upper_price_per_group
0 Sony VAIO Laptop 700 1200
1 Lenovo Thinkpad Laptop 700 1200
2 Dell Vostro Laptop 800 1200
3 HP Elite Laptop 1200 1200
4 Microsoft Lumia Smartphone 200 900
5 HTC One Smartphone 400 900
6 Nexus Smartphone 500 900
7 iPhone Smartphone 900 900
8 Kindle Fire Tablet 150 700
9 Samsung Galaxy Tab Tablet 200 700
10 iPad Tablet 700 700

6. LAG, LEAD 함수

  • 그룹안에서 특정 컬럼의 이전 행 또는 다음 행 값을 구함
함수 내용
LAG 이전 행의 값을 구함
LEAD 다음행의 값을 구함
  • LAG
SELECT A.PRODUCT_NAME, B.GROUP_NAME, A.PRICE
,             LAG (A.PRICE, 1) OVER (PARTITION BY B.GROUP_NAME ORDER BY A.PRICE ) AS PREV_PRICE
, A.PRICE - LAG (A.PRICE, 1) OVER (PARTITION BY B.GROUP_NAME ORDER BY A.PRICE ) AS CUR_PREV_DIFF
FROM PRODUCT A
INNER JOIN PRODUCT_GROUP B
ON (A.GROUP_ID = B.GROUP_ID);

product_name group_name price prev_price cur_prev_diff
0 Sony VAIO Laptop 700 None None
1 Lenovo Thinkpad Laptop 700 700.00 0.00
2 Dell Vostro Laptop 800 700.00 100.00
3 HP Elite Laptop 1200 800.00 400.00
4 Microsoft Lumia Smartphone 200 None None
5 HTC One Smartphone 400 200.00 200.00
6 Nexus Smartphone 500 400.00 100.00
7 iPhone Smartphone 900 500.00 400.00
8 Kindle Fire Tablet 150 None None
9 Samsung Galaxy Tab Tablet 200 150.00 50.00
10 iPad Tablet 700 200.00 500.00
  • LEAD
SELECT A.PRODUCT_NAME, B.GROUP_NAME, A.PRICE
,             LEAD (A.PRICE, 1) OVER ( PARTITION BY B.GROUP_NAME ORDER BY A.PRICE ) AS NEXT_PRICE
, A.PRICE - LEAD (A.PRICE, 1) OVER ( PARTITION BY B.GROUP_NAME ORDER BY A.PRICE )AS CUR_NEXT_DIFF
FROM PRODUCT A
INNER JOIN PRODUCT_GROUP B
ON (A.GROUP_ID = B.GROUP_ID);

product_name group_name price prev_price cur_prev_diff
0 Sony VAIO Laptop 700 700.00 0.00
1 Lenovo Thinkpad Laptop 700 800.00 -100.00
2 Dell Vostro Laptop 800 1200.00 -400.00
3 HP Elite Laptop 1200 None None
4 Microsoft Lumia Smartphone 200 400.00 -200.00
5 HTC One Smartphone 400 500.00 -100.00
6 Nexus Smartphone 500 900.00 -400.00
7 iPhone Smartphone 900 None None
8 Kindle Fire Tablet 150 200.00 -50.00
9 Samsung Galaxy Tab Tablet 200 700.00 -500.00
10 iPad Tablet 700 None None

# 참고

반응형

'데이터 분석 > SQL' 카테고리의 다른 글

[SQL] 6. 서브 쿼리(Sub Query)  (0) 2021.04.19
[SQL] 5. 집합 연산자  (0) 2021.04.19
[SQL] 3. 데이터 집계(Group by)  (0) 2021.04.01
[SQL] 2. 데이터 조인  (0) 2021.03.29
[SQL] 1. 데이터 조회와 필터링  (0) 2021.03.23

+ Recent posts

반응형