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 |
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 |
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 함수
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 |
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 |
다음행의 값을 구함 |
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 |
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 |
# 참고