본문 바로가기

IT Story/SQL Story

SQL 함수: 분석 함수

행 그룹을 기반으로 집계해 이동 평균, 누계, 백분율, 그룹 내 상위 N개의 결과를 계산한다. 

앞 또는 뒤 행 참조하기: LAG, LEAD 함수

하루 전 날짜와 오늘 날짜 데이터를 비교할 때, LAG 또는 LEAD 함수를 사용하면 간편하다. 

LAG 함수는 현재 행에서 바로 앞의 행에 접근하고,

LEAD 함수는 현재 행에서 바로 뒤의 행에 접근한다. 

물론, offset 인자에 전달한 값에 따라 이전 또는 이후 몇 번째 행의 데이터를 참조할지 결정할 수 있다. 

LAG, LEAD 함수의 기본 형식
LAG(scalar_expression [, offeset], [default])
       OVER ([partition_by_clause] order-by_clause)

다음은 stock 테이블에서 symbol =' MSFT'인 데이터를 검색해 현재 행 기준으로 앞 또는 뒤의 행을 참조한다. 앞,뒤 데이터 비교를 쉽게 하기 위해 기준 열인 close를 가운데 두었다. 

SELECT

date,

LAG([close]) OVER(ORDER BY [close] ASC) AS lag_price, 

[close],

LEAD([close]) OVER(ORDER BY [close] ASC) AS lead_price

FROM stock

WHERE symbol ='MSFT'

AND date >= '2021-01-01' AND date < '2021-01-20'

결과

date                                                    lag_price                          close                                    lead_price
2021-01-06 00:00:00.000               NULL                                 212.25                                212.649993896484
2021-01-15 00:00:00.000               212.25                               212.649993896484         213.020004272461
2021-01-14 00:00:00.000               212.649993896484        213.020004272461         214.929992675781
2021-01-12 00:00:00.000               213.020004272461        214.929992675781         216.339996337891
2021-01-13 00:00:00.000               214.929992675781        216.339996337891         216.440002441406
2021-01-19 00:00:00.000               216.339996337891        216.440002441406         217.490005493164
2021-01-11 00:00:00.000               216.440002441406        217.490005493164         217.690002441406
2021-01-04 00:00:00.000               217.490005493164        217.690002441406         217.899993896484
2021-01-05 00:00:00.000               217.690002441406        217.899993896484         218.289993286133
2021-01-07 00:00:00.000               217.899993896484        218.289993286133         219.619995117188
2021-01-08 00:00:00.000               218.289993286133        219.619995117188         NULL

close 열 기준으로 왼쪽은 현재 행의 앞, 오른쪽은 현재 행의 뒤에 있는 행을 참조함을 알 수 있다. 
다음은 offset를 2로 설정한 쿼리이다.

SELECT

date,

LAG([close], 2) OVER(ORDER BY [close] ASC) AS lag_price, 

[close],

LEAD([close],2) OVER(ORDER BY [close] ASC) AS lead_price

FROM stock

WHERE symbol ='MSFT'

AND date >= '2021-01-01' AND date < '2021-01-20'

결과

date                                                    lag_price                         close                                lead_price
2021-01-06 00:00:00.000               NULL                               212.25                             213.020004272461
2021-01-15 00:00:00.000               NULL                               212.649993896484      214.929992675781
2021-01-14 00:00:00.000               212.25                             213.020004272461      216.339996337891
2021-01-12 00:00:00.000               212.649993896484      214.929992675781      216.440002441406
2021-01-13 00:00:00.000               213.020004272461      216.339996337891      217.490005493164
2021-01-19 00:00:00.000               214.929992675781      216.440002441406      217.690002441406
2021-01-11 00:00:00.000               216.339996337891      217.490005493164      217.899993896484
2021-01-04 00:00:00.000               216.440002441406      217.690002441406      218.289993286133
2021-01-05 00:00:00.000               217.490005493164      217.899993896484      219.619995117188
2021-01-07 00:00:00.000               217.690002441406      218.289993286133      NULL
2021-01-08 00:00:00.000               217.899993896484      219.619995117188      NULL

 

누적 분포 계산하기: CUME_DIST 함수

그룹내 누적 분포를 계산한다. 즉, 그룹에서 지정한 값의 상대 위치를 계산한다. 

CUME_DIST 함수의 기본 형식
CUME_DIST()
       OVER ([partition_by_clause] order-by_clause)

예를 들어, Department 그룹별로 Rate 값의 누적 분포를 계산했을 때, 가장 높은 Rate는 1이고 그 하위는 1을 기준으로 몇 분위에 있는지를 나타낸다.

CUME_DIST 함수는 0초과 1이하 범위의 값을 반환하며, 같은 값은 항상 같은 누적 분푯값으로 계산한다. CUME_DIST 함수는 기본적으로 NULL 값을 포함하며 가능한 한 가장 낮은 값으로 취급한다. 

SELECT

symbol, sector,

ROUND(close_price, 0),

CUME_DIST OVER (ORDER BY ROUND (close_price, 0) DESC) AS cume_dist

FROM nasdaq_company

결과

symbol                   sector             (열 이름 없음)                                     cume_dist
BTC-USD            NULL                   60776                                     0.00011213276519399
^DJI                      NULL                   36328                                     0.000224265530387979
YM=F                   NULL                   34697                                     0.000336398295581969
^N225                  NULL                   29535                                     0.000448531060775959
NAV                     Capital Goods   18600                                     0.000560663825969948
^IXIC                   NULL                   15972                                     0.000672796591163938

 

상대 순위 계산하기: PERCENT_RANK 함수

PERCENT_RNAK 함수는 상대 순위를 계산한다. 또한 쿼리 결과 집합 또는 파티션 내의 상대 순위를 평가할 수 있다. CUME_DIST 함수와 유사하나 누적 분포가 아닌 분포 순위라는 점이 다르다

PERCENT_RANK 함수의 기본 형식
PERCENT_RANK()
       OVER ([partition_by_clause] order-by_clause)

모든 그룹의 첫번째 행은 0이고, 기본적으로 NULL 값을 포함하며 가능한 한 가장 낮은 값으로 취급한다. NULL도 유효 데이터로 취급한다.

SELECT

symbol, sector,

ROUND(close_price, 0),

PERCENT_RANK() OVER (ORDER BY ROUND (close_price, 0) DESC) AS PERCENT_RANK

FROM nasdaq_company

결과

symbol                          sector                          (열 이름 없음)                          PERCENT_RANK
BTC-USD                    NULL                          60776                                                   0
^DJI                              NULL                          36328                                                   0.000112145340361108
YM=F                           NULL                          34697                                                   0.000224290680722216
^N225                          NULL                          29535                                                   0.000336436021083324
NAV                             Capital Goods           18600                                                   0.000448581361444432

 

중앙값 계산하기: PERCENTILE_CONT, PERCENTILE_DISC 함수

PERCENTILE_CONT, PERCENTILE_DISC 함수의 기본 형식
PERCENTILE_CONT(numeric_literal)
        WITHIN GROUP (ORDER BY order_by_expression [ASC or DESC])
        OVER ([partition_by_clause])

numeric_literal에 전달할 인자는 계산할 백분위 수이며 범위는 0.0~1.0 사이이다. WITHIN GROUP(ORDER  BY order_by_exrpession [ASC or DESC])는 정렬할 숫잣값 목록을 지정하며 기본 정렬 순서는 오름차순인 ASC이다.

PERCENTILE_CONT, PERCENTILE_DISC 함수는 NULL 값을 무시한다. 

PERCENTILE_CONT 함수는 데이터셋에 있거나 없는 적절한 값을 보간한 결과를 반환하며,

PERCENTILE_DISC 함수는 정확한 위치의 실젯값인 중위수를 추출할 때 사용한다. 

SELECT

symbol, sector, close_price,

PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY close_price) OVER(PARTITION BY sector) As PT_COUNT, 

PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY close_price) OVER(PARTITION BY sector) As PT_DISC

FROM nasdaq_company

WHERE close_price is NOT NULL

결과

symbol                      sector                           close_price                                     PT_COUNT                                      PT_DISC
EURUSD=X             NULL                           1.15553498268127                      2030.52001953125                           1820
^VIX                           NULL                           16.4799995422363                      2030.52001953125                           1820
DBA                           NULL                           19.2700004577637                      2030.52001953125                           1820
SI=F                           NULL                           22.0209999084473                      2030.52001953125                           1820

정렬된 첫번째/마지막 행의 값 구하기: FIRST_VALUE, LAST_VALUE 함수

stock 테이블에서 특정 기간 동안 symbol 그룹별로 가장 높은 종가를 구한 뒤 해당 가격과 현재 가격의 차이가 얼마인지 검색한 쿼리이다.

SELECT

symbol, date, [close], [close] - (FIRST_VALUE([close]) OVER(PARTITION BY symbol ORDER BY [close] DESC))

FROM stock

WHERE date >= '2021-01-01' AND date < '2021-02-1'

ORDER BY symbol, date

결과

symbol        date                                               close                                    (열 이름 없음)
^CMC200 2021-01-05 00:00:00.000            654.447998046875           -106.835998535156
^CMC200 2021-01-06 00:00:00.000            696.783020019531            -64.5009765625
^CMC200 2021-01-07 00:00:00.000            749.794982910156            -11.489013671875
^CMC200 2021-01-08 00:00:00.000            761.283996582031            0
^CMC200 2021-01-11 00:00:00.000            654.158996582031            -107.125

'IT Story > SQL Story' 카테고리의 다른 글

하루 동안 상승/하락 종목 분석하기  (0) 2022.12.06
주가 분석하기  (0) 2022.12.06
SQL 함수: 순위 함수  (0) 2022.12.06
SQL 함수: 수학 함수  (0) 2022.12.05
SQL 함수: 집계 함수  (0) 2022.12.05