MySQL8.0 데이터베이스 창 기능

 

소개

      데이터베이스 윈도우 기능은 SQL에서 사용되는 기능으로, 데이터를 더 잘 분석하고 처리하기 위해 결과 집합의 데이터를 그룹화하고 정렬하는 데 사용할 수 있습니다. 윈도우 함수는 집계 함수와 달리 여러 행의 데이터를 하나의 행으로 집계하지 않고 각 데이터 행을 유지하고 그룹화 및 정렬합니다.

일반적인 윈도우 기능에는 ROW_NUMBER(), RANK(), DENSE_RANK(), NTILE(), LAG(), LEAD() 등이 있습니다. 이러한 기능은 사용자가 데이터를 더 잘 이해하고 분석할 수 있도록 그룹화되고 정렬된 결과 집합을 생성하는 데 도움이 됩니다.

예를 들어 ROW_NUMBER() 함수를 사용하여 하나 이상의 필드를 기반으로 결과 집합을 그룹화하고 각 그룹 내에서 행 번호를 생성하여 사용자가 데이터를 쉽게 추적할 수 있도록 합니다. LAG() 및 LEAD() 함수를 사용하여 결과 집합의 각 행 전후에 데이터를 추출하여 사용자가 현재 행 전후의 데이터를 볼 수 있도록 합니다.

윈도우 기능은 사용자가 데이터를 더 잘 분석하고 처리하기 위해 결과 집합의 데이터를 그룹화하고 정렬하는 데 도움이 되는 SQL의 매우 유용한 도구입니다.

MySQL 공식 문서https://dev.mysql.com/doc/refman/8.0/en/window-functions.html

참고 : 창 열기 기능에 대한 공식적인 설명은 MySQL8.0 이후에만 제공됩니다.

1. 창 함수와 집계 함수의 차이점은 무엇입니까?

  • 데이터 처리 범위: 집계 함수는 전체 데이터 테이블 또는 데이터 세트에 대해서만 작동할 수 있으며 계산 결과는 단일 값입니다. 창 기능은 각 행에서 작동할 수 있으며 계산 결과는 각 행에 표시됩니다.
  • 계산 결과 : 집계 함수의 계산 결과는 1개뿐이며 일반적으로 합산, 평균값, 최대값/최소값 계산 등과 같은 작업을 수행하는 데 사용됩니다. 창 함수는 여러 결과를 가질 수 있지만 쿼리 결과 집합의 각 행에 대해 추가 열을 제공합니다.
  • 구문: 집계 함수는 일반적으로 SELECT 절과 SELECT 문의 HAVING 절에서 사용되는 반면, 윈도우 함수는 일반적으로 OVER 키워드 다음에 사용됩니다.

2. 공식적으로 설명된 창 열기 기능

  •  번역하다

공식 성명은 매우 공식적이지만 아직 이해하기가 조금 어렵습니다.

3. 윈도우 함수의 분할

3.1, 일련 번호

  • ROW_NUMBER() : 이 함수는 결과 집합을 하나 이상의 필드로 그룹화하고 각 그룹 내에서 행 번호를 생성하여 사용자가 데이터를 쉽게 추적할 수 있도록 합니다.
  • RANK() : 이 함수는 하나 이상의 필드에 따라 결과 집합을 정렬하고 각 정렬에서 순위를 생성하여 사용자가 데이터의 크기와 순서를 이해할 수 있도록 합니다.
  • DENSE_RANK() : 이 함수는 하나 이상의 필드에 따라 결과 집합을 정렬하고 각 정렬에서 순위를 생성할 수 있지만 생략된 위치는 RANK() 함수보다 하나 적습니다.

3.2 배포

  • PERCENT RANK() : 이 함수는 데이터 세트에서 각 값의 백분율 순위를 계산하는 데 사용됩니다.
  • CUME_DIST() : 데이터셋의 각 값에 대한 누적 밀도 순위를 계산하는 데 사용되는 함수입니다.

3.3 전후

  • LAG() : 이 함수는 결과 집합의 각 행 앞의 데이터를 추출하여 사용자가 현재 행 앞의 데이터를 볼 수 있도록 합니다.
  • LEAD() : 이 함수는 사용자가 현재 행 이후의 데이터를 볼 수 있도록 결과 집합의 각 행 이후 데이터를 추출할 수 있습니다.

3.4, 시작과 끝

  • FIRST_VALUE() : 이 함수는 결과 집합의 정렬된 파티션에서 첫 번째 값을 반환합니다.
  • LAST_VALUE() : 이 함수는 결과 집합의 정렬된 파티션에서 마지막 값을 반환합니다.

3.5 기타

  • NTILE() : 이 함수는 하나 이상의 필드에 따라 결과 세트를 그룹화하고 각 그룹을 지정된 수의 버킷에 분배하여 사용자가 데이터를 더 잘 분석하고 그룹화할 수 있도록 합니다.
  • NTH_VALUE() : 이 함수는 결과 집합의 정렬된 파티션에서 n번째 행의 값을 반환합니다.

넷째, 문법의 사용

4.1 문법 구조

<窗口函数> OVER ([PARTITION BY <分组列>] [ORDER BY <排序列> {ASC|DESC}] [<行窗口>|<范围窗口>] [<开始位置>|<结束位置>|<长度>])
  • <윈도우 함수>는 SUM, AVG, MAX, MIN, COUNT 등과 같이 실행할 집계 함수를 나타냅니다.
  • <그룹화 열>은 그룹화할 열을 나타냅니다.
  • <정렬 열>은 정렬할 열을 나타내며 여러 정렬 열을 쉼표로 구분하여 지정할 수 있습니다.
  • <행 창> 및 <범위 창>은 각각 행 수준 창과 범위 수준 창을 나타냅니다.
  • <시작 위치>, <종료 위치> 및 <길이>는 창의 시작 위치, 종료 위치 및 길이를 나타냅니다.

 MySQL 8.0에서 행 창은 연속된 행의 집합으로 전체적으로 간주되며 창 함수 계산에 사용할 수 있습니다.

행 창은 다음 키워드로 지정됩니다.

  • ROWS: 행 창을 나타냅니다.
  • BETWEEN: 행 창의 시작 및 끝 위치를 지정하는 데 사용됩니다.
  • PRECEDING: 행 창의 시작 위치를 나타냅니다.
  • FOLLOWING: 행 창의 끝 위치를 나타냅니다.

일반적으로 사용되는 행 창 지정 방법:

  • ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW: 결과 집합의 첫 번째 행부터 현재 행을 포함하여 현재 행까지를 나타냅니다.
  • ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING: 현재 행을 포함하여 결과 집합의 현재 행에서 마지막 행까지를 나타냅니다.
  • ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING: 현재 행을 포함하여 전후의 각 행을 나타냅니다.

설명: 행 창은 각 그룹의 합계, 평균, 개수 및 기타 집계 작업을 계산하는 데 사용할 수 있으며 각 행의 순위, 누적 합계 및 기타 작업을 계산하는 데 사용할 수도 있습니다.

4.2 윈도잉 함수로서의 일반 집계 함수

  • 일반 집계 함수는 전체 데이터 테이블 또는 데이터 세트에 대해서만 작동할 수 있으며 계산 결과는 단일 값입니다. 창 기능은 각 행에서 작동할 수 있으며 계산 결과는 각 행에 표시됩니다.

4.2.1, 테이블 구조

DROP TABLE IF EXISTS `order_for_goods`;
CREATE TABLE `order_for_goods`  (
  `order_id` int(0) NOT NULL AUTO_INCREMENT,
  `user_id` int(0) NULL DEFAULT NULL,
  `money` decimal(10, 2) NULL DEFAULT NULL,
  `quantity` int(0) NULL DEFAULT NULL,
  `join_time` datetime(0) NULL DEFAULT NULL,
  PRIMARY KEY (`order_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

4.2.2, 테이블 데이터

INSERT INTO order_for_goods (user_id, money, quantity, join_time )
VALUES
	( 1001, 1800.90, 1, '2023-06-07'),
	( 1001, 3600.89, 5, '2023-05-02'),
	( 1001, 1000.10, 6, '2023-01-08'),
	( 1002, 1100.90, 9, '2023-04-07'),
	( 1002, 4500.99, 1, '2023-03-14'),
	( 1003, 2500.10, 3, '2023-02-14'),
	( 1002, 2500.90, 1, '2023-03-14'),
	( 1003, 2500.90, 1, '2022-12-12'),
	( 1003, 2500.90, 2, '2022-09-08'),
    ( 1003, 6000.90, 8, '2023-01-10');

4.2.3 윈도우 함수로서의 일반 함수

1. 성명은 다음과 같다

select 
	*,
	sum(money) over(partition by user_id order by order_id) as alias_sum,
	avg(money) over(partition by user_id order by order_id) as alias_avg,
	max(money) over(partition by user_id order by order_id) as alias_max,
	min(money) over(partition by user_id order by order_id) as alias_min,
	count(money) over(partition by user_id order by order_id) as alias_count
from order_for_goods;
  • order_for_goods 테이블에서 모든 열을 선택하고 각 사용자에 대한 각 주문의 총 금액, 평균 금액, 최대 금액, 최소 금액 및 횟수를 계산했습니다.
  • 이 쿼리는 sum(), avg(), max(), min() 및 count() 함수를 사용하여 각 주문의 합계, 평균, 최대값, 최소값 및 개수를 계산합니다. 이러한 함수 뒤에는 계산 창을 지정하는 over() 절이 옵니다. 이 예에서 창은 user_id로 분할되고 order_id로 정렬됩니다.

2. 쿼리 결과는 다음과 같이 선택한 컬럼과 계산된 별칭 컬럼을 리턴합니다.

4.3, 일련 번호 기능

4.3.1, ROW_NUMBER() 함수

1. 문을 실행

select *
from (
	select *,row_number() over(partition by user_id order by money desc) as alias_row_number
	from order_for_goods) t
where alias_row_number<=3;
  • 위의 SQL 문은 윈도우 함수 row_number()를 사용하여 각 파티션의 행에 일련 번호를 할당합니다. 그런 다음 외부 쿼리는 이러한 서수에서 처음 세 개의 가장 높은 행을 선택합니다.
  • 내부 쿼리는 order_for_goods 테이블에서 모든 열을 선택하고 row_number() 함수를 사용하여 각 파티션 내의 행에 서수를 할당합니다. 이 예에서 하위 쿼리는 데이터를 user_id 열로 분할하고 money 열을 기준으로 내림차순으로 정렬합니다.
  • 외부 쿼리는 서수가 3보다 작거나 같은 내부 쿼리의 결과에서 행을 선택합니다. 이 행은 파티션의 상위 3개 행에 해당합니다.

2. 실행 결과

 3. 명령문 실행

select *
from (
	select *,row_number() over(partition by user_id order by money desc) as alias_row_number
	from order_for_goods) t
where alias_row_number<=1;
  •  위의 쿼리문은 alias_row_number<=3이 alias_row_number<=1로 변경되어 결과가 파티션에서 가장 높은 행만 반환한다는 점을 제외하면 이전 쿼리문과 유사합니다.

4. 실행 결과

 요약: 다양하게 생각할 수 있습니다. 예를 들어, 각 상품 분야에서 상위 3개 매출을 세십시오. 창 설정을 사용하면 많은 문제를 해결할 수 있고 유지 관리하기 어렵고 이해할 수 없는 많은 SQL 논리를 피할 수 있습니다.

 4.3.2, 랭크() 함수

1. 문을 실행

select 
	*,
    rank() over(partition by user_id order by money desc) as alias_rank 
from order_for_goods;
  •  위의 SQL 문은 윈도우 함수 rank()를 사용하여 각 사용자에 대한 별칭 순위(alias_rank)를 계산합니다.
  • rank() 함수는 각 파티션 내의 연속 순위에 대한 순위 값을 계산하므로 이 명령문은 각 사용자에 대한 별칭 순위를 계산합니다.
  • 문은 조건을 지정하지 않으므로 order_for_goods 테이블의 모든 행과 열을 반환합니다. 특정 행이나 열을 쿼리해야 하는 경우 select 절에 해당 조건이나 열 이름을 지정할 수 있습니다.

 2. 실행 결과

 4.3.3, DENSE_RANK() 함수

 1. 문을 실행

select 
	*,
    dense_rank() over(partition by user_id order by money desc) as alias_dense_rank 
from order_for_goods;
  •  위의 SQL 문은 윈도우 함수 dense_rank()를 사용하여 각 사용자에 대한 별칭 밀집 순위(alias_dense_rank)를 계산합니다.
  • dense_rank() 함수는 각 파티션 내 순위에 대한 순위 값을 계산하고 동일한 순위 값을 가진 인접한 행에 대해 순위 값을 연속적으로 할당합니다. 따라서 이 명령문은 각 사용자에 대한 별칭 밀집 순위를 계산합니다.
  • 문은 조건을 지정하지 않으므로 order_for_goods 테이블의 모든 행과 열을 반환합니다. 특정 행이나 열을 쿼리해야 하는 경우 select 절에 해당 조건이나 열 이름을 지정할 수 있습니다.

 2. 실행 결과

 4.3.4 위의 세 가지 일련번호 기능 비교

 1. 문을 실행

select 
	*,
 	row_number() over(partition by user_id order by money desc) as alias_row_number,
    rank() over(partition by user_id order by money desc) as alias_rank,
 	dense_rank() over(partition by user_id order by money desc) as alias_dense_rank
from order_for_goods;
  •  order_for_goods 테이블에서 모든 열을 선택하고 각 주문에서 각 사용자의 총 금액을 계산하고 각 주문에서 각 사용자의 서수, 순위 및 밀집 순위를 계산했습니다.
  • 이 쿼리는 row_number(), rank() 및 dense_rank() 함수를 사용하여 각 파티션 내 행의 서수, 순위 및 밀집 순위를 계산합니다. 이러한 함수 뒤에는 계산 창을 지정하는 over() 절이 옵니다. 이 예에서 창은 user_id로 분할되고 money 열을 기준으로 내림차순으로 정렬됩니다.

  2. 실행 결과

4.4 분배 기능

4.4.1, PERCENT RANK() 함수

  1. 문을 실행

select 
	*,
	percent_rank() over(partition by user_id order by money desc) as alias_percent_rank
from order_for_goods;
  •  order_for_goods 테이블에서 모든 열을 선택하고 각 주문에서 각 사용자의 총 금액을 계산하고 각 주문에서 각 사용자의 백분율 순위를 계산했습니다.
  • 이 쿼리는 percent_rank() 함수를 사용하여 각 파티션 내 행의 백분위수 순위를 계산합니다. 이 함수 다음에는 계산 창을 지정하는 over() 절이 옵니다. 이 예에서 창은 user_id로 분할되고 money 열을 기준으로 내림차순으로 정렬됩니다.

  2. 실행 결과

4.4.2, CUME_DIST() 함수

  1. 문을 실행

select 
	*,
	cume_dist() over(partition by user_id order by money desc) as alias_percent_rank
from order_for_goods;
  •  order_for_goods 테이블에서 모든 열을 선택하고 각 주문에서 각 사용자의 총 금액을 계산하고 각 주문에서 각 사용자의 누적 백분율을 계산했습니다.
  • 이 쿼리는 cume_dist() 함수를 사용하여 각 파티션 내 행의 누적 백분율을 계산합니다. 이 함수 다음에는 계산 창을 지정하는 over() 절이 옵니다. 이 예에서 창은 user_id로 분할되고 money 열을 기준으로 내림차순으로 정렬됩니다.

  2. 실행 결과

4.5 앞면과 뒷면 기능

4.5.1 LAG() 함수

1. 문법적 설명

  • LAG() 함수는 시계열에서 지정된 기간만큼 앞으로 이동하는 데 사용되는 함수입니다.
LAG(expression, offset, default_value)
  1.  표현식: 평가할 열
  2.  오프셋: 앞으로 처음 몇 행의 값
  3.  default_value: 값이 없을 경우 기본값으로 설정 가능

2. 명령문 실행

select 
	*,
	lag(join_time, 1, 0) over(partition by user_id order by join_time desc) as alias_lag
from order_for_goods;

 3. 실행 결과

4.5.2 LEAD() 함수

1. 문법적 설명

  • LEAD() 함수는 시계열에서 지정된 기간만큼 뒤로 이동하는 데 사용되는 함수입니다.
LAG(expression, offset, default_value)
  1.  표현식: 평가할 열
  2.  offset: 뒤로 행 수의 값
  3.  default_value: 값이 없을 경우 기본값으로 설정 가능

2. 명령문 실행

select 
	*,
	lead(join_time, 1, 0) over(partition by user_id order by join_time desc) as alias_lead
from order_for_goods;

3. 실행 결과

4.6 닫기 기능

4.6.1, FIRST_VALUE() 함수

1. 문법적 설명

  • FIRST_VALUE: 창의 첫 번째 행의 값을 가져옵니다.
FIRST_VALUE(expression)
  1.  표현식: 첫 번째 행의 값을 얻기 위해 열 또는 계산 결과를 지정하는 표현식입니다.

2. 실행 구문

select 
	*,
	first_value(money) over(partition by user_id order by join_time desc) as alias_first_value
from order_for_goods;
  • 사용자가 지정된 시간 범위에 대한 데이터가 없는 경우 LAST_VALUE() 함수는 기본값인 NULL을 반환합니다. 

 3. 실행 결과

 

4.6.2, LAST_VALUE() 함수

1. 문법적 설명

  • LAST_VALUE: 창의 마지막 행 값을 가져옵니다.
LAST_VALUE(expression)
  1.  표현식: 마지막 행의 값을 얻기 위해 열 또는 계산 결과를 지정하는 표현식입니다.

2. 실행 구문

select 
	*,
	last_value(money) over(partition by user_id order by join_time) as alias_last_value
from order_for_goods;
  • 사용자가 지정된 시간 범위에 대한 데이터가 없는 경우 LAST_VALUE() 함수는 기본값인 NULL을 반환합니다.

2. 실행 결과

 3. 설명

  1. LAST_VALUE()가 창의 마지막 값을 취하지 않는다는 것을 알 수 있습니다. 창은 user_id로 분할되고 join_time 열로 정렬됩니다. 1001 분할의 돈을 1800.90으로 반환하는 것이 합리적입니다. 이유는 무엇입니까?
  2. 그 이유는 LAST_VALUE()의 기본 통계 범위가 무제한 이전 행과 현재 행 사이의 행이기 때문입니다.

  3. 검증

select 
	*,
	last_value(money) over(partition by user_id order by join_time) as alias_last_value1,
	last_value(money) over(partition by user_id order by join_time rows between unbounded preceding and current row) as alias_last_value2,
	last_value(money) over(partition by user_id order by join_time rows between unbounded preceding and unbounded following) as alias_last_value3
from order_for_goods;
  •  별칭 alias_last_value2는 LAST_VALUE()의 기본 통계 범위가 무제한 이전 행과 현재 행 사이의 행임을 확인했음을 알 수 있습니다. 현재 행이 계산되기 전에.)
  •  별칭 alias_last_value3은 무한 선행과 무한 후행 사이의 행(경계 없이 현재 행에서 앞뒤로 계산이 수행됨을 나타냄, 즉 전체 파티션을 계산한 결과)을 모두에서 얻을 수 있음을 알 수 있습니다. statistics, user_id 파티션, join_time 컬럼이 정렬되고 1001 파티션에서 money 필드의 마지막 거래 금액이 1800.90으로 리턴됩니다.
+----------+---------+---------+----------+---------------------+------------------+------------------+------------------+
| order_id | user_id | money   | quantity | join_time           | alias_last_value | alias_last_value | alias_last_value |
+----------+---------+---------+----------+---------------------+------------------+------------------+------------------+
|       34 |    1001 | 1000.10 |        6 | 2023-01-08 00:00:00 |          1000.10 |          1000.10 |          1800.90 |
|       33 |    1001 | 3600.89 |        5 | 2023-05-02 00:00:00 |          3600.89 |          3600.89 |          1800.90 |
|       32 |    1001 | 1800.90 |        1 | 2023-06-07 00:00:00 |          1800.90 |          1800.90 |          1800.90 |
|       36 |    1002 | 4500.99 |        1 | 2023-03-14 00:00:00 |          2500.90 |          4500.99 |          1100.90 |
|       38 |    1002 | 2500.90 |        1 | 2023-03-14 00:00:00 |          2500.90 |          2500.90 |          1100.90 |
|       35 |    1002 | 1100.90 |        9 | 2023-04-07 00:00:00 |          1100.90 |          1100.90 |          1100.90 |
|       40 |    1003 | 2500.90 |        2 | 2022-09-08 00:00:00 |          2500.90 |          2500.90 |          2500.10 |
|       39 |    1003 | 2500.90 |        1 | 2022-12-12 00:00:00 |          2500.90 |          2500.90 |          2500.10 |
|       41 |    1003 | 6000.90 |        8 | 2023-01-10 00:00:00 |          6000.90 |          6000.90 |          2500.10 |
|       37 |    1003 | 2500.10 |        3 | 2023-02-14 00:00:00 |          2500.10 |          2500.10 |          2500.10 |
+----------+---------+---------+----------+---------------------+------------------+------------------+------------------+
10 rows in set (0.00 sec)

4.7 기타 기능

4.7.1, NTILE() 함수

1. 문법적 설명

  • NTILE()은 쿼리 결과 집합을 지정된 수의 버킷으로 나누고 버킷의 크기에 따라 각 버킷에 데이터를 분배하는 데 사용됩니다.
NTILE(bucket_size)
  1.  bucket_size: 결과 집합을 나눌 버킷 수를 나타내는 정수 매개 변수입니다.

2. 명령문 실행

select 
	*,  
	ntile(1) over(partition by user_id order by join_time desc) as alias_ntile1,
	ntile(2) over(partition by user_id order by join_time desc) as alias_ntile2,
	ntile(3) over(partition by user_id order by join_time desc) as alias_ntile3
from order_for_goods;
  •  쿼리는 데이터 세트를 지정된 수의 버킷에 균등하게 분배하고 각 행이 속한 버킷 번호를 반환할 수 있는 윈도우 함수 NTILE()를 사용합니다.
  •  별칭 "alias_ntile3"을 예로 들어 보겠습니다. 이 쿼리에서 ntile(3)은 각 사용자를 3개의 그룹으로 나누는 것을 의미하고, partition by user_id는 user_id로 그룹화하는 것을 의미하고, order by join_time desc는 join_time을 내림차순으로 정렬하는 것을 의미합니다.
  • ntile(2)이면 두 그룹으로 나눈다는 의미이고, ntile(1)은 한 그룹으로 나눈다는 뜻이다.

3. 실행 결과

 설명: NTILE() 함수는 정렬된 데이터 세트를 지정된 수의 버킷에 균등하게 분배하고 각 행에 버킷 번호를 할당할 수 있습니다. 고르게 분배할 수 없는 경우 버킷 번호가 작은 버킷이 추가 행을 할당하며 각 버킷에 배치할 수 있는 행의 수는 최대 1개까지 다릅니다.

4.7.2, NTH_VALUE() 함수

1. 문법적 설명

  • NTH_VALUE() 함수는 정렬된 데이터 세트에서 지정된 위치의 값을 계산하기 위해 SQL에서 사용되는 창 함수입니다.
NTH_VALUE(expression, nth_parameter)
  1.  표현식: 단일 값으로 평가되는 평가할 표현식입니다.
  2.  nth_parameter: 계산할 값의 시퀀스 번호를 나타내는 정수 매개변수입니다.

2. 명령문 실행

select 
	*,  
    nth_value(money, 2) over(partition by user_id order by join_time ) as alias_nth_value
from order_for_goods;
  • 사용자가 지정된 시간 범위 내에 데이터가 없는 경우 NTH_VALUE() 함수는 기본값 NULL을 반환합니다. 

3. 실행 결과

 

Supongo que te gusta

Origin blog.csdn.net/weixin_50002038/article/details/131011696
Recomendado
Clasificación