:meta-keywords: cubrid aggregate, database aggregate function, cubrid analytic, database analytic function, json aggregate function :meta-description: CUBRID Aggregate/Analytic function is used when you want to analyze data and extract some results. :tocdepth: 3 ************** 집계/ë¶„ì„ í•¨ìˆ˜ ************** .. contents:: 개요 ==== 집계/ë¶„ì„ í•¨ìˆ˜ëŠ” ë°ì´í„°ë¥¼ ë¶„ì„하여 ì–´ë–¤ 결과를 ì¶”ì¶œí•˜ê³ ìž í• ë•Œ 사용하는 함수ì´ë‹¤. * 집계 함수는 그룹 별로 ê·¸ë£¹í•‘ëœ ê²°ê³¼ë¥¼ 리턴하며, 그룹핑 대ìƒì´ ë˜ëŠ” 칼럼만 ì¶œë ¥í•œë‹¤. * ë¶„ì„ í•¨ìˆ˜ëŠ” 그룹 별로 ê·¸ë£¹í•‘ëœ ê²°ê³¼ë¥¼ 리턴하ë˜, 그룹핑ë˜ì§€ ì•Šì€ ì¹¼ëŸ¼ì„ í¬í•¨í•˜ì—¬ í•˜ë‚˜ì˜ ê·¸ë£¹ì— ëŒ€í•´ 여러 ê°œì˜ í–‰ì„ ì¶œë ¥í• ìˆ˜ 있다. 예를 들어 집계/ë¶„ì„ í•¨ìˆ˜ëŠ” 다ìŒê³¼ ê°™ì€ ì§ˆë¬¸ì— ëŒ€í•œ ë‹µì„ êµ¬í•˜ê¸° 위해 사용ë 수 있다. 1. ì—°ë„별 ì´ íŒë§¤ ê¸ˆì•¡ì€ ì–´ë–»ê²Œ ë˜ëŠ”ê°€? 2. ì—°ë„별로 그룹지어 가장 íŒë§¤ ê¸ˆì•¡ì´ ë†’ì€ ì›”ë¶€í„° 순서대로 ì¶œë ¥í•˜ë ¤ë©´ 어떻게 하는가? 3. ì—°ë„별로 그룹지어 ì—°ë„별, 월별 순서대로 누ì íŒë§¤ ê¸ˆì•¡ì„ ì¶œë ¥í•˜ë ¤ë©´ 어떻게 하는가? 1.ì€ ì§‘ê³„ 함수로 ë‹µì„ êµ¬í• ìˆ˜ 있으며, 2., 3.ì€ ë¶„ì„ í•¨ìˆ˜ë¡œ ë‹µì„ êµ¬í• ìˆ˜ 있다. ìœ„ì˜ ì§ˆë¬¸ë“¤ì€ ë‹¤ìŒì˜ SQL문으로 작성ë 수 있다. 다ìŒì€ ê° ë…„ë„ì˜ ì›”ë³„ íŒë§¤ ê¸ˆì•¡ì„ ì €ìž¥í•˜ê³ ìžˆëŠ” í…Œì´ë¸”ì´ë‹¤. .. code-block:: sql CREATE TABLE sales_mon_tbl ( yyyy INT, mm INT, sales_sum INT ); INSERT INTO sales_mon_tbl VALUES (2000, 1, 1000), (2000, 2, 770), (2000, 3, 630), (2000, 4, 890), (2000, 5, 500), (2000, 6, 900), (2000, 7, 1300), (2000, 8, 1800), (2000, 9, 2100), (2000, 10, 1300), (2000, 11, 1500), (2000, 12, 1610), (2001, 1, 1010), (2001, 2, 700), (2001, 3, 600), (2001, 4, 900), (2001, 5, 1200), (2001, 6, 1400), (2001, 7, 1700), (2001, 8, 1110), (2001, 9, 970), (2001, 10, 690), (2001, 11, 710), (2001, 12, 880), (2002, 1, 980), (2002, 2, 750), (2002, 3, 730), (2002, 4, 980), (2002, 5, 1110), (2002, 6, 570), (2002, 7, 1630), (2002, 8, 1890), (2002, 9, 2120), (2002, 10, 970), (2002, 11, 420), (2002, 12, 1300); 1. ì—°ë„별 ì´ íŒë§¤ ê¸ˆì•¡ì€ ì–´ë–»ê²Œ ë˜ëŠ”ê°€? .. code-block:: sql SELECT yyyy, sum(sales_sum) FROM sales_mon_tbl GROUP BY yyyy; :: yyyy sum(sales_sum) ============================= 2000 14300 2001 11870 2002 13450 2. ì—°ë„별로 그룹지어 가장 íŒë§¤ ê¸ˆì•¡ì´ ë†’ì€ ì›”ë¶€í„° 순서대로 ì¶œë ¥í•˜ë ¤ë©´ 어떻게 하는가? .. code-block:: sql SELECT yyyy, mm, sales_sum, RANK() OVER (PARTITION BY yyyy ORDER BY sales_sum DESC) AS rnk FROM sales_mon_tbl; :: yyyy mm sales_sum rnk ==================================================== 2000 9 2100 1 2000 8 1800 2 2000 12 1610 3 2000 11 1500 4 2000 7 1300 5 2000 10 1300 5 2000 1 1000 7 2000 6 900 8 2000 4 890 9 2000 2 770 10 2000 3 630 11 2000 5 500 12 2001 7 1700 1 2001 6 1400 2 2001 5 1200 3 2001 8 1110 4 2001 1 1010 5 2001 9 970 6 2001 4 900 7 2001 12 880 8 2001 11 710 9 2001 2 700 10 2001 10 690 11 2001 3 600 12 2002 9 2120 1 2002 8 1890 2 2002 7 1630 3 2002 12 1300 4 2002 5 1110 5 2002 1 980 6 2002 4 980 6 2002 10 970 8 2002 2 750 9 2002 3 730 10 2002 6 570 11 2002 11 420 12 3. ì—°ë„별로 그룹지어 ì—°ë„별, 월별 순서대로 누ì íŒë§¤ ê¸ˆì•¡ì„ ì¶œë ¥í•˜ë ¤ë©´ 어떻게 하는가? .. code-block:: sql SELECT yyyy, mm, sales_sum, SUM(sales_sum) OVER (PARTITION BY yyyy ORDER BY yyyy, mm) AS a_sum FROM sales_mon_tbl; :: yyyy mm sales_sum a_sum ==================================================== 2000 1 1000 1000 2000 2 770 1770 2000 3 630 2400 2000 4 890 3290 2000 5 500 3790 2000 6 900 4690 2000 7 1300 5990 2000 8 1800 7790 2000 9 2100 9890 2000 10 1300 11190 2000 11 1500 12690 2000 12 1610 14300 2001 1 1010 1010 2001 2 700 1710 2001 3 600 2310 2001 4 900 3210 2001 5 1200 4410 2001 6 1400 5810 2001 7 1700 7510 2001 8 1110 8620 2001 9 970 9590 2001 10 690 10280 2001 11 710 10990 2001 12 880 11870 2002 1 980 980 2002 2 750 1730 2002 3 730 2460 2002 4 980 3440 2002 5 1110 4550 2002 6 570 5120 2002 7 1630 6750 2002 8 1890 8640 2002 9 2120 10760 2002 10 970 11730 2002 11 420 12150 2002 12 1300 13450 집계 함수와 ë¶„ì„ í•¨ìˆ˜ ë¹„êµ ========================== **집계 함수(aggregate functions)**\ 는 í–‰ë“¤ì˜ ê·¸ë£¹ì— ê¸°ë°˜í•˜ì—¬ ê° ê·¸ë£¹ 당 í•˜ë‚˜ì˜ ê²°ê³¼ë¥¼ 반환한다. **GROUP BY** ì ˆì„ í¬í•¨í•˜ë©´ ê° ê·¸ë£¹ë§ˆë‹¤ 한 í–‰ì˜ ì§‘ê³„ 결과를 반환한다. **GROUP BY** ì ˆì„ ìƒëžµí•˜ë©´ ì „ì²´ í–‰ì— ëŒ€í•´ 한 í–‰ì˜ ì§‘ê³„ 결과를 반환한다. **HAVING** ì ˆì€ **GROUP BY** ì ˆì´ ìžˆëŠ” 질ì˜ì— ì¡°ê±´ì„ ì¶”ê°€í• ë•Œ 사용한다. ëŒ€ë¶€ë¶„ì˜ ì§‘ê³„ 함수는 **DISTINCT**, **UNIQUE** ì œì•½ ì¡°ê±´ì„ ì‚¬ìš©í• ìˆ˜ 있다. **GROUP BY ... HAVING** ì ˆì— ëŒ€í•´ì„œëŠ” :ref:`group-by-clause` ì„ ì°¸ê³ í•œë‹¤. **ë¶„ì„ í•¨ìˆ˜(analytic functions)**\ 는 í–‰ë“¤ì˜ ê²°ê³¼ì— ê¸°ë°˜í•˜ì—¬ 집계 ê°’ì„ ê³„ì‚°í•œë‹¤. ë¶„ì„ í•¨ìˆ˜ëŠ” **OVER** ì ˆ ë’¤ì˜ <*partition_by_clause*>\ì— ì˜í•´ ì§€ì •ëœ ê·¸ë£¹ë“¤(ì´ ì ˆì´ ìƒëžµë˜ë©´ ëª¨ë“ í–‰ì„ í•˜ë‚˜ì˜ ê·¸ë£¹ìœ¼ë¡œ ë´„)ì„ ê¸°ì¤€ìœ¼ë¡œ 한 ê°œ ì´ìƒì˜ í–‰ì„ ë°˜í™˜í• ìˆ˜ 있다는 ì ì—서 집계 함수와 다르다. ë¶„ì„ í•¨ìˆ˜ëŠ” íŠ¹ì • í–‰ ì§‘í•©ì— ëŒ€í•´ 다양한 통계를 허용하기 위해 ê¸°ì¡´ì˜ ì§‘ê³„ 함수들 ì¼ë¶€ì— **OVER** ë¼ëŠ” 새로운 ë¶„ì„ ì ˆì´ í•¨ê»˜ 사용ëœë‹¤. :: function_name ([<argument_list>]) OVER (<analytic_clause>) <analytic_clause>::= [<partition_by_clause>] [<order_by_clause>] <partition_by_clause>::= PARTITION BY value_expr[, value_expr]... <order_by_clause>::= ORDER BY { expression | position | column_alias } [ ASC | DESC ] [, { expression | position | column_alias } [ ASC | DESC ] ] ... * <*partition_by_clause*>: 하나 ì´ìƒì˜ *value_expr* ì— ê¸°ë°˜í•œ 그룹들로, ì§ˆì˜ ê²°ê³¼ë¥¼ ë¶„í• í•˜ê¸° 위해 **PARTITION BY** ì ˆì„ ì‚¬ìš©í•œë‹¤. * <*order_by_clause*>: <*partition_by_clause*>ì— ì˜í•œ ë¶„í• (partition) ë‚´ì—서 ë°ì´í„°ì˜ ì •ë ¬ ë°©ì‹ì„ 명시한다. 여러 ê°œì˜ í‚¤ë¡œ ì •ë ¬í• ìˆ˜ 있다. <*partition_by_clause*>ê°€ ìƒëžµë 경우 ì „ì²´ ê²°ê³¼ ì…‹ ë‚´ì—서 ë°ì´í„°ë¥¼ ì •ë ¬í•œë‹¤. ì •ë ¬ëœ ìˆœì„œì— ì˜í•´ ì•žì˜ ê°’ì„ í¬í•¨í•˜ì—¬ 누ì 한 ë ˆì½”ë“œì˜ ì¹¼ëŸ¼ ê°’ì„ ëŒ€ìƒìœ¼ë¡œ 함수를 ì 용하여 계산한다. ë¶„ì„ í•¨ìˆ˜ì˜ OVER ì ˆ ë’¤ì— í•¨ê»˜ 사용ë˜ëŠ” ORDER BY/PARTITION BY ì ˆì˜ í‘œí˜„ì‹ì— 따른 ë™ìž‘ ë°©ì‹ì€ 다ìŒê³¼ 같다. * ORDER BY/PARTITION BY <ìƒìˆ˜ê°€ 아닌 표현ì‹> (예: i, sin(i+1)): 표현ì‹ì€ ì •ë ¬/ë¶„í• (ordering/partitioning)ì— ì‚¬ìš©ë¨. * ORDER BY/PARTITION BY <ìƒìˆ˜> (예: 1): ìƒìˆ˜ëŠ” SELECT ë¦¬ìŠ¤íŠ¸ì˜ ì¹¼ëŸ¼ 위치로 간주ë¨. * ORDER BY/PARTITION BY <ìƒìˆ˜ 표현ì‹> (예: 1+0): ìƒìˆ˜ 표현ì‹ì€ 무시ë˜ì–´, ì •ë ¬/ë¶„í• (ordering/partitioning)ì— ì‚¬ìš©ë˜ì§€ 않ìŒ. OVER 함수 ë‚´ì— "ORDER BY" ì ˆì„ ëª…ì‹œí•´ì•¼ 하는 ë¶„ì„ í•¨ìˆ˜ ====================================================== ë‹¤ìŒ ë¶„ì„ í•¨ìˆ˜ë“¤ì€ ìˆœì„œê°€ 필요하므로 OVER 함수 ë‚´ì— "ORDER BY" ì ˆì„ ëª…ì‹œí•´ì•¼ 하는 ë¶„ì„ í•¨ìˆ˜ë“¤ì´ë‹¤. "ORDER BY" ì ˆì´ ìƒëžµë˜ëŠ” 경우 오류가 ë°œìƒí•˜ê±°ë‚˜ ì¶œë ¥ ê²°ê³¼ì— ëŒ€í•´ ì •í™•í•œ 순서를 보장하지 않는다는 ì ì— ì£¼ì˜í•œë‹¤. * :func:`CUME_DIST` * :func:`DENSE_RANK` * :func:`LAG` * :func:`LEAD` * :func:`NTILE` * :func:`PERCENT_RANK` * :func:`RANK` * :func:`ROW_NUMBER` AVG === .. function:: AVG ([ DISTINCT | DISTINCTROW | UNIQUE | ALL ] expression) .. function:: AVG ([ DISTINCT | DISTINCTROW | UNIQUE | ALL ] expression) OVER (<analytic_clause>) :noindex: **AVG** 함수는 집계 함수 ë˜ëŠ” ë¶„ì„ í•¨ìˆ˜ë¡œ 사용ë˜ë©°, ëª¨ë“ í–‰ì— ëŒ€í•œ ì—°ì‚°ì‹ ê°’ì˜ ì‚°ìˆ í‰ê· ì„ êµ¬í•œë‹¤. í•˜ë‚˜ì˜ ì—°ì‚°ì‹ *expression* ë§Œ ì¸ìžë¡œ ì§€ì •ë˜ë©°, ì—°ì‚°ì‹ ì•žì— **DISTINCT** ë˜ëŠ” **UNIQUE** 키워드를 í¬í•¨ì‹œí‚¤ë©´ ì—°ì‚°ì‹ ê°’ 중 ì¤‘ë³µì„ ì œê±°í•œ 후 í‰ê· ì„ êµ¬í•˜ê³ , 키워드가 ìƒëžµë˜ê±°ë‚˜ **ALL** ì¸ ê²½ìš°ì—는 ëª¨ë“ ê°’ì— ëŒ€í•´ì„œ í‰ê· ì„ êµ¬í•œë‹¤. :param expression: 수치 ê°’ì„ ë°˜í™˜í•˜ëŠ” ìž„ì˜ì˜ ì—°ì‚°ì‹ì„ ì§€ì •í•œë‹¤. ì»¬ë ‰ì…˜ íƒ€ìž…ì˜ ë°ì´í„°ë¥¼ 반환하는 ì—°ì‚°ì‹ì€ ì§€ì •ë 수 없다. :param ALL: ëª¨ë“ ê°’ì— ëŒ€í•´ í‰ê· ì„ êµ¬í•˜ê¸° 위해 사용ë˜ë©°, 기본값ì´ë‹¤. :param DISTINCT,DISTINCTROW,UNIQUE: ì¤‘ë³µì´ ì œê±°ëœ ìœ ì¼í•œ ê°’ì— ëŒ€í•´ì„œë§Œ í‰ê· ì„ êµ¬í•˜ê¸° 위해 사용ëœë‹¤. :rtype: DOUBLE 다ìŒì€ *demodb* ì—서 한êµì´ íšë“한 ê¸ˆë©”ë‹¬ì˜ í‰ê· 수를 반환하는 ì˜ˆì œì´ë‹¤. .. code-block:: sql SELECT AVG(gold) FROM participant WHERE nation_code = 'KOR'; :: avg(gold) ========================== 9.600000000000000e+00 다ìŒì€ *demodb* ì—서 nation_codeê°€ 'AU'로 시작하는 êµê°€ì— 대해 ì—°ë„ ë³„ë¡œ íšë“한 금메달 수와 해당 ì—°ë„ê¹Œì§€ì˜ ê¸ˆë©”ë‹¬ 누ì ì— ëŒ€í•œ í‰ê· 합계를 ì¶œë ¥í•˜ëŠ” ì˜ˆì œì´ë‹¤. .. code-block:: sql SELECT host_year, nation_code, gold, AVG(gold) OVER (PARTITION BY nation_code ORDER BY host_year) avg_gold FROM participant WHERE nation_code like 'AU%'; :: host_year nation_code gold avg_gold ======================================================================= 1988 'AUS' 3 3.000000000000000e+00 1992 'AUS' 7 5.000000000000000e+00 1996 'AUS' 9 6.333333333333333e+00 2000 'AUS' 16 8.750000000000000e+00 2004 'AUS' 17 1.040000000000000e+01 1988 'AUT' 1 1.000000000000000e+00 1992 'AUT' 0 5.000000000000000e-01 1996 'AUT' 0 3.333333333333333e-01 2000 'AUT' 2 7.500000000000000e-01 2004 'AUT' 2 1.000000000000000e+00 다ìŒì€ 위 ì˜ˆì œì—서 **OVER** ë¶„ì„ ì ˆ ì´í•˜ì˜ "ORDER BY host_year" ì ˆì„ ì œê±°í•œ 것으로, avg_goldì˜ ê°’ì€ ëª¨ë“ ì—°ë„ì˜ ê¸ˆë©”ë‹¬ í‰ê· 으로 nation_code별로 ê° ì—°ë„ì—서 ëª¨ë‘ ê°™ì€ ê°’ì„ ê°€ì§„ë‹¤. .. code-block:: sql SELECT host_year, nation_code, gold, AVG(gold) OVER (PARTITION BY nation_code) avg_gold FROM participant WHERE nation_code LIKE 'AU%'; :: host_year nation_code gold avg_gold ========================================================================== 2004 'AUS' 17 1.040000000000000e+01 2000 'AUS' 16 1.040000000000000e+01 1996 'AUS' 9 1.040000000000000e+01 1992 'AUS' 7 1.040000000000000e+01 1988 'AUS' 3 1.040000000000000e+01 2004 'AUT' 2 1.000000000000000e+00 2000 'AUT' 2 1.000000000000000e+00 1996 'AUT' 0 1.000000000000000e+00 1992 'AUT' 0 1.000000000000000e+00 1988 'AUT' 1 1.000000000000000e+00 COUNT ===== .. function:: COUNT (*) .. function:: COUNT (*) OVER (<analytic_clause>) :noindex: .. function:: COUNT ([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) :noindex: .. function:: COUNT ([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) OVER (<analytic_clause>) :noindex: **COUNT** 함수는 집계 함수 ë˜ëŠ” ë¶„ì„ í•¨ìˆ˜ë¡œ 사용ë˜ë©°, 질ì˜ë¬¸ì´ 반환하는 ê²°ê³¼ í–‰ë“¤ì˜ ê°œìˆ˜ë¥¼ 반환한다. 별표(*)를 ì§€ì •í•˜ë©´ ì¡°ê±´ì„ ë§Œì¡±í•˜ëŠ” ëª¨ë“ í–‰(**NULL** ê°’ì„ ê°€ì§€ëŠ” í–‰ í¬í•¨)ì˜ ê°œìˆ˜ë¥¼ 반환하며, **DISTINCT** ë˜ëŠ” **UNIQUE** 키워드를 ì—°ì‚°ì‹ ì•žì— ì§€ì •í•˜ë©´ ì¤‘ë³µì„ ì œê±°í•œ 후 ìœ ì¼í•œ ê°’ì„ ê°€ì§€ëŠ” í–‰(**NULL** ê°’ì„ ê°€ì§€ëŠ” í–‰ì€ í¬í•¨í•˜ì§€ 않ìŒ)ì˜ ê°œìˆ˜ë§Œ 반환한다. ë”°ë¼ì„œ, 반환ë˜ëŠ” ê°’ì€ í•ìƒ í° ì •ìˆ˜ 타입ì´ë©°, **NULL** ì€ ë°˜í™˜ë˜ì§€ 않는다. :param expression: ìž„ì˜ì˜ ì—°ì‚°ì‹ì´ë‹¤. :param ALL: 주어진 expressionì˜ ëª¨ë“ í–‰ì˜ ê°œìˆ˜ë¥¼ 구하기 위해 사용ë˜ë©°, 기본값ì´ë‹¤. :param DISTINCT,DISTINCTROW,UNIQUE: ì¤‘ë³µì´ ì œê±°ëœ ìœ ì¼í•œ ê°’ì„ ê°€ì§€ëŠ” í–‰ì˜ ê°œìˆ˜ë¥¼ 구하기 위해 사용ëœë‹¤. :rtype: BIGINT ì—°ì‚°ì‹ *expression* ì€ ìˆ˜ì¹˜í˜• ë˜ëŠ” 문ìžì—´ íƒ€ìž…ì€ ë¬¼ë¡ , ì»¬ë ‰ì…˜ 타입 칼럼과 오브ì 트 ë„ë©”ì¸(ì‚¬ìš©ìž ì •ì˜ í´ëž˜ìФ)ì„ ê°€ì§€ëŠ” ì¹¼ëŸ¼ë„ ì§€ì •ë 수 있다. 다ìŒì€ *demodb* ì—서 ì—대 올림픽 중ì—서 마스코트가 ì¡´ìž¬í–ˆì—ˆë˜ ì˜¬ë¦¼í”½ì˜ ìˆ˜ë¥¼ 반환하는 ì˜ˆì œì´ë‹¤. .. code-block:: sql SELECT COUNT(*) FROM olympic WHERE mascot IS NOT NULL; :: count(*) ====================== 9 다ìŒì€ *demodb* ì—서 nation_codeê°€ 'AUT'ì¸ êµê°€ì˜ 참가 ì„ ìˆ˜ì˜ ì¢…ëª©(event)별 ì¸ì› 수를 ì¢…ëª©ì´ ë°”ë€” 때마다 누ì 하여 ì¶œë ¥í•œ ì˜ˆì œì´ë‹¤. 가장 마지막 줄ì—는 ëª¨ë“ ì¸ì› 수가 ì¶œë ¥ëœë‹¤. .. code-block:: sql SELECT nation_code, event, name, COUNT(*) OVER (ORDER BY event) co FROM athlete WHERE nation_code='AUT'; :: nation_code event name co ======================================================================================== 'AUT' 'Athletics' 'Kiesl Theresia' 2 'AUT' 'Athletics' 'Graf Stephanie' 2 'AUT' 'Equestrian' 'Boor Boris' 6 'AUT' 'Equestrian' 'Fruhmann Thomas' 6 'AUT' 'Equestrian' 'Munzner Joerg' 6 'AUT' 'Equestrian' 'Simon Hugo' 6 'AUT' 'Judo' 'Heill Claudia' 9 'AUT' 'Judo' 'Seisenbacher Peter' 9 'AUT' 'Judo' 'Hartl Roswitha' 9 'AUT' 'Rowing' 'Jonke Arnold' 11 'AUT' 'Rowing' 'Zerbst Christoph' 11 'AUT' 'Sailing' 'Hagara Roman' 15 'AUT' 'Sailing' 'Steinacher Hans Peter' 15 'AUT' 'Sailing' 'Sieber Christoph' 15 'AUT' 'Sailing' 'Geritzer Andreas' 15 'AUT' 'Shooting' 'Waibel Wolfram Jr.' 17 'AUT' 'Shooting' 'Planer Christian' 17 'AUT' 'Swimming' 'Rogan Markus' 18 CUME_DIST ========= .. function:: CUME_DIST(expression[, expression] ...) WITHIN GROUP (<order_by_clause>) .. function:: CUME_DIST() OVER ([<partition_by_clause>] <order_by_clause>) :noindex: **CUME_DIST** 함수는 집계 함수 ë˜ëŠ” ë¶„ì„ í•¨ìˆ˜ë¡œ 사용ë˜ë©°, ê·¸ë£¹ì˜ ê°’ ë‚´ì—서 명시한 ê°’ì˜ ëˆ„ì ë¶„í¬ ê°’ì„ ë°˜í™˜í•œë‹¤. **CUME_DIST**\ ì— ì˜í•´ 반환ë˜ëŠ” ê°’ì˜ ë²”ìœ„ëŠ” 0보다 í¬ê³ 1보다 작거나 같다. ê°™ì€ ê°’ì˜ ìž…ë ¥ ì¸ìžì— 대한 **CUME_DIST** í•¨ìˆ˜ì˜ ë°˜í™˜ ê°’ì€ í•ìƒ ê°™ì€ ëˆ„ì ë¶„í¬ ê°’ìœ¼ë¡œ í‰ê°€ëœë‹¤. :param expression: 수치 ë˜ëŠ” 문ìžì—´ì„ 반환하는 ì—°ì‚°ì‹. ì¹¼ëŸ¼ì´ ì˜¬ 수 없다. :param order_by_clause: **ORDER BY** ì ˆ ë’¤ì— ì˜¤ëŠ” 칼럼 ì´ë¦„ì€ *expression* ê°œìˆ˜ë§Œí¼ ë§¤í•‘ë˜ì–´ì•¼ 한다. :rtype: DOUBLE .. seealso:: :func:`PERCENT_RANK`, :ref:`CUME_DIST와 PERCENT_RANK ë¹„êµ <compare-cd-pr>` 집계 í•¨ìˆ˜ì¸ ê²½ìš°, **CUME_DIST** 함수는 **ORDER BY** ì ˆì— ëª…ì‹œëœ ìˆœì„œë¡œ ì •ë ¬í•œ 후, 집계 ê·¸ë£¹ì— ìžˆëŠ” í–‰ì—서 ê°€ìƒ(hypothetical) í–‰ì˜ ìƒëŒ€ì ì¸ ìœ„ì¹˜ë¥¼ 반환한다. ì´ë•Œ, ê°€ìƒ í–‰ì´ ìƒˆë¡œ ìž…ë ¥ë˜ëŠ” 것으로 ê°„ì£¼í•˜ê³ ìœ„ì¹˜ë¥¼ 계산한다. 즉, ("ì–´ë–¤ í–‰ì˜ ëˆ„ì ëœ RANK" + 1)/("집계 그룹 ì „ì²´ í–‰ì˜ ê°œìˆ˜" + 1)ì„ ë°˜í™˜í•œë‹¤. ë¶„ì„ í•¨ìˆ˜ì¸ ê²½ìš°, **PARTITION BY**\ ì— ì˜í•´ 나누어진 그룹별로 ê° í–‰ì„ **ORDER BY** ì ˆì— ëª…ì‹œëœ ìˆœì„œë¡œ ì •ë ¬í•œ 후 그룹 ë‚´ ê°’ì˜ ìƒëŒ€ì ì¸ ìœ„ì¹˜ë¥¼ 반환한다. ìƒëŒ€ì ì¸ ìœ„ì¹˜ëŠ” ìž…ë ¥ ì¸ìž 값보다 작거나 ê°™ì€ ê°’ì„ ê°€ì§„ í–‰ì˜ ê°œìˆ˜ë¥¼ 그룹 ë‚´ ì´ í–‰(*partition_by_clause*\ ì— ì˜í•´ ê·¸ë£¹í•‘ëœ í–‰ ë˜ëŠ” ì „ì²´ í–‰)ì˜ ê°œìˆ˜ë¡œ 나눈 것ì´ë‹¤. 즉, (ì–´ë–¤ í–‰ì˜ ëˆ„ì ëœ RANK)/(그룹 ë‚´ í–‰ì˜ ê°œìˆ˜)를 반환한다. 예를 들어, ì „ì²´ 10ê°œì˜ í–‰ 중ì—서 RANKê°€ 1ì¸ í–‰ì˜ ê°œìˆ˜ê°€ 2ê°œì´ë©´ 첫번째 행과 ë‘번째 í–‰ì˜ **CUME_DUST** ê°’ì€ "2/10 = 0.2"ê°€ ëœë‹¤. 다ìŒì€ ì´ í•¨ìˆ˜ì˜ ì˜ˆì—서 사용ë 스키마 ë° ë°ì´í„°ì´ë‹¤. .. code-block:: sql CREATE TABLE scores(id INT PRIMARY KEY AUTO_INCREMENT, math INT, english INT, pe CHAR, grade INT); INSERT INTO scores(math, english, pe, grade) VALUES(60, 70, 'A', 1), (60, 70, 'A', 1), (60, 80, 'A', 1), (60, 70, 'B', 1), (70, 60, 'A', 1) , (70, 70, 'A', 1) , (80, 70, 'C', 1) , (70, 80, 'C', 1), (85, 60, 'C', 1), (75, 90, 'B', 1); INSERT INTO scores(math, english, pe, grade) VALUES(95, 90, 'A', 2), (85, 95, 'B', 2), (95, 90, 'A', 2), (85, 95, 'B', 2), (75, 80, 'D', 2), (75, 85, 'D', 2), (75, 70, 'C', 2), (65, 95, 'A', 2), (65, 95, 'A', 2), (65, 95, 'A', 2); 다ìŒì€ 집계 함수로 사용ë˜ëŠ” 예로, *math*, *english*, *pe* 3ê°œì˜ ì¹¼ëŸ¼ì— ëŒ€í•œ ê°ê°ì˜ 누ì ë¶„í¬ ê°’ì„ ë”í•´ 3으로 나눈 결과를 ì¶œë ¥í•œë‹¤. .. code-block:: sql SELECT CUME_DIST(60, 70, 'D') WITHIN GROUP(ORDER BY math, english, pe) AS cume FROM scores; :: 1.904761904761905e-01 다ìŒì€ ë¶„ì„ í•¨ìˆ˜ë¡œ 사용ë˜ëŠ” 예로, *math*, *english*, *pe* 3ê°œ ì¹¼ëŸ¼ì„ ê¸°ì¤€ìœ¼ë¡œ ê° í–‰ì˜ ëˆ„ì ë¶„í¬ë¥¼ ì¶œë ¥í•œë‹¤. .. code-block:: sql SELECT id, math, english, pe, grade, CUME_DIST() OVER(ORDER BY math, english, pe) AS cume_dist FROM scores ORDER BY cume_dist; :: id math english pe grade cume_dist ==================================================================================================== 1 60 70 'A' 1 1.000000000000000e-01 2 60 70 'A' 1 1.000000000000000e-01 4 60 70 'B' 1 1.500000000000000e-01 3 60 80 'A' 1 2.000000000000000e-01 18 65 95 'A' 2 3.500000000000000e-01 19 65 95 'A' 2 3.500000000000000e-01 20 65 95 'A' 2 3.500000000000000e-01 5 70 60 'A' 1 4.000000000000000e-01 6 70 70 'A' 1 4.500000000000000e-01 8 70 80 'C' 1 5.000000000000000e-01 17 75 70 'C' 2 5.500000000000000e-01 15 75 80 'D' 2 6.000000000000000e-01 16 75 85 'D' 2 6.500000000000000e-01 10 75 90 'B' 1 7.000000000000000e-01 7 80 70 'C' 1 7.500000000000000e-01 9 85 60 'C' 1 8.000000000000000e-01 12 85 95 'B' 2 9.000000000000000e-01 14 85 95 'B' 2 9.000000000000000e-01 11 95 90 'A' 2 1.000000000000000e+00 13 95 90 'A' 2 1.000000000000000e+00 다ìŒì€ ë¶„ì„ í•¨ìˆ˜ë¡œ 사용ë˜ëŠ” 예로, *math*, *english*, *pe* 3ê°œ ì¹¼ëŸ¼ì„ ê¸°ì¤€ìœ¼ë¡œ *grade* 칼럼으로 그룹핑하여 ê° í–‰ì˜ ëˆ„ì ë¶„í¬ë¥¼ ì¶œë ¥í•œë‹¤. .. code-block:: sql SELECT id, math, english, pe, grade, CUME_DIST() OVER(PARTITION BY grade ORDER BY math, english, pe) AS cume_dist FROM scores ORDER BY grade, cume_dist; :: id math english pe grade cume_dist ============================================================================================ 1 60 70 'A' 1 2.000000000000000e-01 2 60 70 'A' 1 2.000000000000000e-01 4 60 70 'B' 1 3.000000000000000e-01 3 60 80 'A' 1 4.000000000000000e-01 5 70 60 'A' 1 5.000000000000000e-01 6 70 70 'A' 1 6.000000000000000e-01 8 70 80 'C' 1 7.000000000000000e-01 10 75 90 'B' 1 8.000000000000000e-01 7 80 70 'C' 1 9.000000000000000e-01 9 85 60 'C' 1 1.000000000000000e+00 18 65 95 'A' 2 3.000000000000000e-01 19 65 95 'A' 2 3.000000000000000e-01 20 65 95 'A' 2 3.000000000000000e-01 17 75 70 'C' 2 4.000000000000000e-01 15 75 80 'D' 2 5.000000000000000e-01 16 75 85 'D' 2 6.000000000000000e-01 12 85 95 'B' 2 8.000000000000000e-01 14 85 95 'B' 2 8.000000000000000e-01 11 95 90 'A' 2 1.000000000000000e+00 13 95 90 'A' 2 1.000000000000000e+00 ìœ„ì˜ ê²°ê³¼ì—서 *id*\ ê°€ 1ì¸ í–‰ì€ *grade*\ ê°€ 1ì¸ 10ê°œì˜ í–‰ 중ì—서 첫번째와 ë‘ë²ˆì§¸ì— ìœ„ì¹˜í•˜ë©°, **CUME_DUST**\ ì˜ ê°’ì€ 2/10, 즉 0.2ê°€ ëœë‹¤. idê°€ 5ì¸ í–‰ì€ *grade*\ ê°€ 1ì¸ 10ê°œì˜ í–‰ 중ì—서 ë‹¤ì„¯ë²ˆì§¸ì— ìœ„ì¹˜í•˜ë©°, **CUME_DUST**\ ì˜ ê°’ì€ 5/10, 즉 0.5ê°€ ëœë‹¤. DENSE_RANK ========== .. function:: DENSE_RANK() OVER ([<partition_by_clause>] <order_by_clause>) **DENSE_RANK** 함수는 ë¶„ì„ í•¨ìˆ˜ë¡œë§Œ 사용ë˜ë©°, **PARTITION BY** ì ˆì— ì˜í•œ 칼럼 ê°’ì˜ ê·¸ë£¹ì—서 ê°’ì˜ ìˆœìœ„ë¥¼ 계산하여 **INTEGER** 로 ì¶œë ¥í•œë‹¤. ê³µë™ ìˆœìœ„ê°€ ì¡´ìž¬í•´ë„ ê·¸ ë‹¤ìŒ ìˆœìœ„ëŠ” 1ì„ ë”한다. 예를 들어, 13ìœ„ì— í•´ë‹¹í•˜ëŠ” í–‰ì´ 3ê°œì—¬ë„ ê·¸ ë‹¤ìŒ í–‰ì˜ ìˆœìœ„ëŠ” 16위가 ì•„ë‹ˆë¼ 14위가 ëœë‹¤. 반면, :func:`RANK` 함수는 ì´ì™€ 달리 ê³µë™ ìˆœìœ„ì˜ ê°œìˆ˜ë§Œí¼ì„ ë”í•´ ë‹¤ìŒ ìˆœìœ„ì˜ ê°’ì„ ê³„ì‚°í•œë‹¤. :rtype: INT 다ìŒì€ ì—대 올림픽ì—서 ì—°ë„별로 ê¸ˆë©”ë‹¬ì„ ë§Žì´ íšë“한 êµê°€ì˜ 금메달 개수와 순위를 ì¶œë ¥í•˜ëŠ” ì˜ˆì œì´ë‹¤. ê³µë™ ìˆœìœ„ì˜ ê°œìˆ˜ëŠ” ë¬´ì‹œí•˜ê³ ë‹¤ìŒ ìˆœìœ„ ê°’ì€ í•ìƒ 1ì„ ë”한다. .. code-block:: sql SELECT host_year, nation_code, gold, DENSE_RANK() OVER (PARTITION BY host_year ORDER BY gold DESC) AS d_rank FROM participant; :: host_year nation_code gold d_rank ============================================================= 1988 'URS' 55 1 1988 'GDR' 37 2 1988 'USA' 36 3 1988 'KOR' 12 4 1988 'HUN' 11 5 1988 'FRG' 11 5 1988 'BUL' 10 6 1988 'ROU' 7 7 1988 'ITA' 6 8 1988 'FRA' 6 8 1988 'KEN' 5 9 1988 'GBR' 5 9 1988 'CHN' 5 9 ... 1988 'CHI' 0 14 1988 'ARG' 0 14 1988 'JAM' 0 14 1988 'SUI' 0 14 1988 'SWE' 0 14 1992 'EUN' 45 1 1992 'USA' 37 2 1992 'GER' 33 3 ... 2000 'RSA' 0 15 2000 'NGR' 0 15 2000 'JAM' 0 15 2000 'BRA' 0 15 2004 'USA' 36 1 2004 'CHN' 32 2 2004 'RUS' 27 3 2004 'AUS' 17 4 2004 'JPN' 16 5 2004 'GER' 13 6 2004 'FRA' 11 7 2004 'ITA' 10 8 2004 'UKR' 9 9 2004 'CUB' 9 9 2004 'GBR' 9 9 2004 'KOR' 9 9 ... 2004 'EST' 0 17 2004 'SLO' 0 17 2004 'SCG' 0 17 2004 'FIN' 0 17 2004 'POR' 0 17 2004 'MEX' 0 17 2004 'LAT' 0 17 2004 'PRK' 0 17 FIRST_VALUE =========== .. function:: FIRST_VALUE(expression) [{RESPECT|IGNORE} NULLS] OVER (<analytic_clause>) **FIRST_VALUE** 함수는 ë¶„ì„ í•¨ìˆ˜ë¡œë§Œ 사용ë˜ë©°, ì •ë ¬ëœ ê°’ ì§‘í•©ì—서 첫번째 ê°’ì„ ë°˜í™˜í•œë‹¤. ì§‘í•© ë‚´ì˜ ì²«ë²ˆì§¸ ê°’ì´ nullì´ë©´ 함수는 **NULL**\ ì„ ë°˜í™˜í•œë‹¤. 그러나, **IGNORE NULLS**\ 를 명시하면 ì§‘í•© ë‚´ì—서 nullì´ ì•„ë‹Œ 첫번째 ê°’ì„ ë°˜í™˜í•˜ê±°ë‚˜, ëª¨ë“ ê°’ì´ nullì¸ ê²½ìš° **NULL**\ ì„ ë°˜í™˜í•œë‹¤. :param expression: 수치 ë˜ëŠ” 문ìžì—´ì„ 반환하는 칼럼 ë˜ëŠ” ì—°ì‚°ì‹. FIRST_VALUE 함수 ë˜ëŠ” 다른 ë¶„ì„ í•¨ìˆ˜ë¥¼ í¬í•¨í• 수 없다. :rtype: expressionì˜ íƒ€ìž… .. seealso:: :func:`LAST_VALUE`, :func:`NTH_VALUE` 다ìŒì€ ì˜ˆì œ 질ì˜ë¥¼ 실행하기 위한 스키마와 ë°ì´í„°ì´ë‹¤. .. code-block:: sql CREATE TABLE test_tbl(groupid int,itemno int); INSERT INTO test_tbl VALUES(1,null); INSERT INTO test_tbl VALUES(1,null); INSERT INTO test_tbl VALUES(1,1); INSERT INTO test_tbl VALUES(1,null); INSERT INTO test_tbl VALUES(1,2); INSERT INTO test_tbl VALUES(1,3); INSERT INTO test_tbl VALUES(1,4); INSERT INTO test_tbl VALUES(1,5); INSERT INTO test_tbl VALUES(2,null); INSERT INTO test_tbl VALUES(2,null); INSERT INTO test_tbl VALUES(2,null); INSERT INTO test_tbl VALUES(2,6); INSERT INTO test_tbl VALUES(2,7); 다ìŒì€ **FIRST_VALUE** 함수를 수행하는 ì§ˆì˜ ë° ê²°ê³¼ì´ë‹¤. .. code-block:: sql SELECT groupid, itemno, FIRST_VALUE(itemno) OVER(PARTITION BY groupid ORDER BY itemno) AS ret_val FROM test_tbl; :: groupid itemno ret_val ======================================= 1 NULL NULL 1 NULL NULL 1 NULL NULL 1 1 NULL 1 2 NULL 1 3 NULL 1 4 NULL 1 5 NULL 2 NULL NULL 2 NULL NULL 2 NULL NULL 2 6 NULL 2 7 NULL .. note:: CUBRID는 **NULL** ê°’ì„ ëª¨ë“ ê°’ë³´ë‹¤ ì•žì˜ ìˆœì„œë¡œ ì •ë ¬í•œë‹¤. 즉, ì•„ëž˜ì˜ SQL1ì€ **ORDER BY** ì ˆì— **NULLS FIRST**\ ê°€ í¬í•¨ëœ SQL2로 í•´ì„ëœë‹¤. :: SQL1: FIRST_VALUE(itemno) OVER(PARTITION BY groupid ORDER BY itemno) AS ret_val SQL2: FIRST_VALUE(itemno) OVER(PARTITION BY groupid ORDER BY itemno NULLS FIRST) AS ret_val 다ìŒì€ **IGNORE NULLS**\ 를 명시하는 예ì´ë‹¤. .. code-block:: sql SELECT groupid, itemno, FIRST_VALUE(itemno) IGNORE NULLS OVER(PARTITION BY groupid ORDER BY itemno) AS ret_val FROM test_tbl; :: groupid itemno ret_val ======================================= 1 NULL NULL 1 NULL NULL 1 NULL NULL 1 1 1 1 2 1 1 3 1 1 4 1 1 5 1 2 NULL NULL 2 NULL NULL 2 NULL NULL 2 6 6 2 7 6 GROUP_CONCAT ============ .. function:: GROUP_CONCAT([DISTINCT] expression [ORDER BY {column | unsigned_int} [ASC | DESC]] [SEPARATOR str_val]) **GROUP_CONCAT** 함수는 집계 함수로만 사용ë˜ë©°, 그룹ì—서 **NULL** ì´ ì•„ë‹Œ ê°’ë“¤ì„ ì—°ê²°í•˜ì—¬ ê²°ê³¼ 문ìžì—´ì„ **VARCHAR** 타입으로 반환한다. ì§ˆì˜ ê²°ê³¼ í–‰ì´ ì—†ê±°ë‚˜ **NULL** ê°’ë§Œ 있으면 **NULL** ì„ ë°˜í™˜í•œë‹¤. :param expression: 수치 ë˜ëŠ” 문ìžì—´ì„ 반환하는 칼럼 ë˜ëŠ” ì—°ì‚°ì‹ :param str_val: 구분ìžë¡œ ì“°ì¼ ë¬¸ìžì—´ :param DISTINCT: ê²°ê³¼ì—서 중복ë˜ëŠ” ê°’ì„ ì œê±°í•œë‹¤. :param ORDER\ BY: ê²°ê³¼ ê°’ì˜ ìˆœì„œë¥¼ ì§€ì •í•œë‹¤. :param SEPARATOR: ê²°ê³¼ ê°’ 사ì´ì— êµ¬ë¶„í• êµ¬ë¶„ìžë¥¼ ì§€ì •í•œë‹¤. ìƒëžµí•˜ë©´ ê¸°ë³¸ê°’ì¸ ì‰¼í‘œ(,)를 구분ìžë¡œ 사용한다. :rtype: STRING 리턴 ê°’ì˜ ìµœëŒ€ í¬ê¸°ëŠ” 시스템 파ë¼ë¯¸í„° **group_concat_max_len** ì˜ ì„¤ì •ì„ ë”°ë¥¸ë‹¤. ê¸°ë³¸ê°’ì€ **1024** ë°”ì´íЏì´ë©°, ìµœì†Œê°’ì€ 4ë°”ì´íЏ, ìµœëŒ€ê°’ì€ INT_MAX(약2G)ë°”ì´íЏì´ë‹¤. ì´ í•¨ìˆ˜ëŠ” **string_max_size_bytes** 파ë¼ë¯¸í„°ì˜ ì˜í–¥ì„ 받으며, **group_concat_max_len**\ì˜ ê°’ì„ **string_max_size_bytes** 보다 í¬ê²Œ ì„¤ì •í•œ 경우 **GROUP_CONCAT** 결과가 **string_max_size_bytes** ê°’ì„ ì´ˆê³¼í•˜ë©´ 오류가 ë°œìƒí•œë‹¤. 중복ë˜ëŠ” ê°’ì„ ì œê±°í•˜ë ¤ë©´ **DISTINCT** ì ˆì„ ì‚¬ìš©í•˜ë©´ ëœë‹¤. 그룹 ê²°ê³¼ì˜ ê°’ 사ì´ì— 사용ë˜ëŠ” 기본 구분ìžëŠ” 쉼표(,)ì´ë©°, 구분ìžë¥¼ 명시ì 으로 í‘œí˜„í•˜ë ¤ë©´ **SEPARATOR** ì ˆê³¼ ê·¸ ë’¤ì— êµ¬ë¶„ìžë¡œ ì‚¬ìš©í• ë¬¸ìžì—´ì„ 추가한다. 구분ìžë¥¼ ì œê±°í•˜ë ¤ë©´ **SEPARATOR** ì ˆ ë’¤ì— ë¹ˆ 문ìžì—´(empty string)ì„ ìž…ë ¥í•œë‹¤. ê²°ê³¼ 문ìžì—´ì— 문ìží˜• ë°ì´í„° íƒ€ìž…ì´ ì•„ë‹Œ 다른 íƒ€ìž…ì´ ì „ë‹¬ë˜ë©´, ì—러를 반환한다. **GROUP_CONCAT** 함수를 ì‚¬ìš©í•˜ë ¤ë©´ 다ìŒì˜ ì¡°ê±´ì„ ë§Œì¡±í•´ì•¼ 한다. * ìž…ë ¥ ì¸ìžë¡œ í•˜ë‚˜ì˜ í‘œí˜„ì‹(ë˜ëŠ” 칼럼)ë§Œ 허용한다. * **ORDER BY** 를 ì´ìš©í•œ ì •ë ¬ì€ ì˜¤ì§ ì¸ìžë¡œ 사용ë˜ëŠ” 표현ì‹(ë˜ëŠ” 칼럼)ì— ì˜í•´ì„œë§Œ 가능하다. * 구분ìžë¡œ 사용ë˜ëŠ” 문ìžì—´ì€ 문ìží˜• 타입만 허용하며, 다른 íƒ€ìž…ì€ í—ˆìš©í•˜ì§€ 않는다. .. code-block:: sql SELECT GROUP_CONCAT(s_name) FROM code; :: group_concat(s_name) ====================== 'X,W,M,B,S,G' .. code-block:: sql SELECT GROUP_CONCAT(s_name ORDER BY s_name SEPARATOR ':') FROM code; :: group_concat(s_name order by s_name separator ':') ====================== 'B:G:M:S:W:X' .. code-block:: sql CREATE TABLE t(i int); INSERT INTO t VALUES (4),(2),(3),(6),(1),(5); SELECT GROUP_CONCAT(i*2+1 ORDER BY 1 SEPARATOR '') FROM t; :: group_concat(i*2+1 order by 1 separator '') ====================== '35791113' LAG === .. function:: LAG(expression[, offset[, default]]) OVER ([<partition_by_clause>] <order_by_clause>) **LAG** 함수는 ë¶„ì„ í•¨ìˆ˜ë¡œë§Œ 사용ë˜ë©° 현재 í–‰ì„ ê¸°ì¤€ìœ¼ë¡œ *offset* 앞 í–‰ì˜ *expression* ê°’ì„ ë°˜í™˜í•œë‹¤. 한 í–‰ì— ìžì²´ ì¡°ì¸(self join) ì—†ì´ ë™ì‹œì— 여러 ê°œì˜ í–‰ì— ì ‘ê·¼í•˜ê³ ì‹¶ì„ ë•Œ ì‚¬ìš©í• ìˆ˜ 있다. :param expression: ìˆ«ìž ë˜ëŠ” 문ìžì—´ì„ 반환하는 칼럼 ë˜ëŠ” ì—°ì‚°ì‹ :param offset: 오프셋 위치를 나타내는 ì •ìˆ˜. ìƒëžµ 시 기본값 1 :param default: 현재 위치ì—서 *offset* ì•žì— ìœ„ì¹˜í•œ *expression* ê°’ì´ NULLì¸ ê²½ìš° ì¶œë ¥í•˜ëŠ” ê°’. 기본값 NULL :rtype: NUMBER or STRING 다ìŒì€ 사번 순으로 ì •ë ¬í•˜ì—¬ ê°™ì€ í–‰ì— ì•žì˜ ì‚¬ë²ˆì„ ê°™ì´ ì¶œë ¥í•˜ëŠ” 예ì´ë‹¤. .. code-block:: sql CREATE TABLE t_emp (name VARCHAR(10), empno INT); INSERT INTO t_emp VALUES ('Amie', 11011), ('Jane', 13077), ('Lora', 12045), ('James', 12006), ('Peter', 14006), ('Tom', 12786), ('Ralph', 23518), ('David', 55); SELECT name, empno, LAG (empno, 1) OVER (ORDER BY empno) prev_empno FROM t_emp; :: name empno prev_empno ================================================ 'David' 55 NULL 'Amie' 11011 55 'James' 12006 11011 'Lora' 12045 12006 'Tom' 12786 12045 'Jane' 13077 12786 'Peter' 14006 13077 'Ralph' 23518 14006 ì´ì™€ëŠ” 반대로, 현재 í–‰ì„ ê¸°ì¤€ìœ¼ë¡œ *offset* ì´í›„ í–‰ì˜ expression ê°’ì„ ë°˜í™˜í•˜ëŠ” :func:`LEAD` 함수를 ì°¸ê³ í•œë‹¤. LAST_VALUE ========== .. function:: LAST_VALUE(expression) [{RESPECT|IGNORE} NULLS] OVER (<analytic_clause>) LAST_VALUE 함수는 ë¶„ì„ í•¨ìˆ˜ë¡œë§Œ 사용ë˜ë©°, ì •ë ¬ëœ ê°’ ì§‘í•©ì—서 마지막 ê°’ì„ ë°˜í™˜í•œë‹¤. ì§‘í•© ë‚´ì˜ ë§ˆì§€ë§‰ ê°’ì´ nullì´ë©´ 함수는 NULLì„ ë°˜í™˜í•œë‹¤. 그러나, IGNORE NULLS를 명시하면 ì§‘í•© ë‚´ì—서 nullì´ ì•„ë‹Œ 마지막 ê°’ì„ ë°˜í™˜í•˜ê±°ë‚˜, ëª¨ë“ ê°’ì´ nullì¸ ê²½ìš° NULLì„ ë°˜í™˜í•œë‹¤. :param expression: 수치 ë˜ëŠ” 문ìžì—´ì„ 반환하는 칼럼 ë˜ëŠ” ì—°ì‚°ì‹. LAST_VALUE 함수 ë˜ëŠ” 다른 ë¶„ì„ í•¨ìˆ˜ë¥¼ í¬í•¨í• 수 없다. :rtype: expressionì˜ íƒ€ìž… .. seealso:: :func:`FIRST_VALUE`, :func:`NTH_VALUE` 다ìŒì€ ì˜ˆì œ 질ì˜ë¥¼ 실행하기 위한 스키마와 ë°ì´í„°ì´ë‹¤. .. code-block:: sql CREATE TABLE test_tbl(groupid int,itemno int); INSERT INTO test_tbl VALUES(1,null); INSERT INTO test_tbl VALUES(1,null); INSERT INTO test_tbl VALUES(1,1); INSERT INTO test_tbl VALUES(1,null); INSERT INTO test_tbl VALUES(1,2); INSERT INTO test_tbl VALUES(1,3); INSERT INTO test_tbl VALUES(1,4); INSERT INTO test_tbl VALUES(1,5); INSERT INTO test_tbl VALUES(2,null); INSERT INTO test_tbl VALUES(2,null); INSERT INTO test_tbl VALUES(2,null); INSERT INTO test_tbl VALUES(2,6); INSERT INTO test_tbl VALUES(2,7); 다ìŒì€ LAST_VALUE 함수를 수행하는 ì§ˆì˜ ë° ê²°ê³¼ì´ë‹¤. .. code-block:: sql SELECT groupid, itemno, LAST_VALUE(itemno) OVER(PARTITION BY groupid ORDER BY itemno) AS ret_val FROM test_tbl; :: groupid itemno ret_val ======================================= 1 NULL NULL 1 NULL NULL 1 NULL NULL 1 1 1 1 2 2 1 3 3 1 4 4 1 5 5 2 NULL NULL 2 NULL NULL 2 NULL NULL 2 6 6 2 7 7 LAST_VALUE 함수는 현재 í–‰ì„ ê¸°ì¤€ìœ¼ë¡œ 계산ëœë‹¤. 즉, ì•„ì§ ë°”ì¸ë”©ë˜ì§€ ì•Šì€ ê°’ì€ ê³„ì‚°ì— í¬í•¨ë˜ì§€ 않는다. 예를 들어, ìœ„ì˜ ê²°ê³¼ì—서 (groupid, itemno) = (1, 1)ì¸ LAST_VALUE í•¨ìˆ˜ì˜ ê°’ì€ 1ì´ê³ , (groupid, itemno) = (1, 2)ì¸ LAST_VALUE í•¨ìˆ˜ì˜ ê°’ì€ 2ì´ë‹¤. .. note:: CUBRID는 NULL ê°’ì„ ëª¨ë“ ê°’ë³´ë‹¤ ì•žì˜ ìˆœì„œë¡œ ì •ë ¬í•œë‹¤. 즉, ì•„ëž˜ì˜ SQL1ì€ ORDER BY ì ˆì— NULLS FIRSTê°€ í¬í•¨ëœ SQL2로 í•´ì„ëœë‹¤. :: SQL1: LAST_VALUE(itemno) OVER(PARTITION BY groupid ORDER BY itemno) AS ret_val SQL2: LAST_VALUE(itemno) OVER(PARTITION BY groupid ORDER BY itemno NULLS FIRST) AS ret_val LEAD ==== .. function:: LEAD(expression, offset[, default]) OVER ([<partition_by_clause>] <order_by_clause>) **LEAD** 함수는 ë¶„ì„ í•¨ìˆ˜ë¡œë§Œ 사용ë˜ë©°, 현재 í–‰ì„ ê¸°ì¤€ìœ¼ë¡œ *offset* ì´í›„ í–‰ì˜ *expression* ê°’ì„ ë°˜í™˜í•œë‹¤. 한 í–‰ì— ìžì²´ ì¡°ì¸(self join) ì—†ì´ ë™ì‹œì— 여러 ê°œì˜ í–‰ì— ì ‘ê·¼í•˜ê³ ì‹¶ì„ ë•Œ ì‚¬ìš©í• ìˆ˜ 있다. :param expression: ìˆ«ìž ë˜ëŠ” 문ìžì—´ì„ 반환하는 칼럼 ë˜ëŠ” ì—°ì‚°ì‹ :param offset: 오프셋 위치를 나타내는 ì •ìˆ˜. ìƒëžµ 시 기본값 1 :param default: 현재 위치ì—서 *offset* ì•žì— ìœ„ì¹˜í•œ *expression* ê°’ì´ NULLì¸ ê²½ìš° ì¶œë ¥í•˜ëŠ” ê°’. 기본값 NULL :rtype: NUMBER or STRING 다ìŒì€ 사번 순으로 ì •ë ¬í•˜ì—¬ ê°™ì€ í–‰ì— ë‹¤ìŒ ì‚¬ë²ˆì„ ê°™ì´ ì¶œë ¥í•˜ëŠ” 예ì´ë‹¤. .. code-block:: sql CREATE TABLE t_emp (name VARCHAR(10), empno INT); INSERT INTO t_emp VALUES ('Amie', 11011), ('Jane', 13077), ('Lora', 12045), ('James', 12006), ('Peter', 14006), ('Tom', 12786), ('Ralph', 23518), ('David', 55); SELECT name, empno, LEAD (empno, 1) OVER (ORDER BY empno) next_empno FROM t_emp; :: name empno next_empno ================================================ 'David' 55 11011 'Amie' 11011 12006 'James' 12006 12045 'Lora' 12045 12786 'Tom' 12786 13077 'Jane' 13077 14006 'Peter' 14006 23518 'Ralph' 23518 NULL 다ìŒì€ tbl_board í…Œì´ë¸”ì—서 현재 í–‰ì„ ê¸°ì¤€ìœ¼ë¡œ ì•žì˜ í–‰ê³¼ ì´í›„ í–‰ì˜ titleì„ ê°™ì´ ì¶œë ¥í•˜ëŠ” 예ì´ë‹¤. .. code-block:: sql CREATE TABLE tbl_board (num INT, title VARCHAR(50)); INSERT INTO tbl_board VALUES (1, 'title 1'), (2, 'title 2'), (3, 'title 3'), (4, 'title 4'), (5, 'title 5'), (6, 'title 6'), (7, 'title 7'); SELECT num, title, LEAD (title,1,'no next page') OVER (ORDER BY num) next_title, LAG (title,1,'no previous page') OVER (ORDER BY num) prev_title FROM tbl_board; :: num title next_title prev_title =============================================================================== 1 'title 1' 'title 2' NULL 2 'title 2' 'title 3' 'title 1' 3 'title 3' 'title 4' 'title 2' 4 'title 4' 'title 5' 'title 3' 5 'title 5' 'title 6' 'title 4' 6 'title 6' 'title 7' 'title 5' 7 'title 7' NULL 'title 6' 다ìŒì€ tbl_board í…Œì´ë¸”ì—서 íŠ¹ì • í–‰ì„ ê¸°ì¤€ìœ¼ë¡œ ì•žì˜ í–‰ê³¼ ì´í›„ í–‰ì˜ íƒ€ì´í‹€ì„ ê°™ì´ ì¶œë ¥í•˜ëŠ” 예ì´ë‹¤. WHERE ì¡°ê±´ì´ ê´„í˜¸ ì•ˆì— ìžˆìœ¼ë©´ í•˜ë‚˜ì˜ í–‰ë§Œ ì„ íƒë˜ê³ , ì•žì˜ í–‰ê³¼ ì´í›„ í–‰ì´ ì¡´ìž¬í•˜ì§€ 않게 ë˜ì–´ next_titleê³¼ prev_titleì˜ ê°’ì´ NULLì´ ë¨ì— ìœ ì˜í•œë‹¤. .. code-block:: sql SELECT * FROM ( SELECT num, title, LEAD(title,1,'no next page') OVER (ORDER BY num) next_title, LAG(title,1,'no previous page') OVER (ORDER BY num) prev_title FROM tbl_board ) WHERE num=5; :: num title next_title prev_title =============================================================================== 5 'title 5' 'title 6' 'title 4' MAX === .. function:: MAX([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) .. function:: MAX([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) OVER (<analytic_clause>) :noindex: **MAX** 함수는 집계 함수 ë˜ëŠ” ë¶„ì„ í•¨ìˆ˜ë¡œ 사용ë˜ë©°, ëª¨ë“ í–‰ì— ëŒ€í•˜ì—¬ ì—°ì‚°ì‹ ê°’ 중 최대 ê°’ì„ êµ¬í•œë‹¤. í•˜ë‚˜ì˜ ì—°ì‚°ì‹ *expression* ë§Œ ì¸ìžë¡œ ì§€ì •ëœë‹¤. 문ìžì—´ì„ 반환하는 ì—°ì‚°ì‹ì— 대해서는 ì‚¬ì „ 순서를 기준으로 ë’¤ì— ë‚˜ì˜¤ëŠ” 문ìžì—´ì´ 최대 ê°’ì´ ë˜ê³ , 수치를 반환하는 ì—°ì‚°ì‹ì— 대해서는 í¬ê¸°ê°€ 가장 í° ê°’ì´ ìµœëŒ€ ê°’ì´ë‹¤. :param expression: 수치 ë˜ëŠ” 문ìžì—´ì„ 반환하는 í•˜ë‚˜ì˜ ì—°ì‚°ì‹ì„ ì§€ì •í•œë‹¤. ì»¬ë ‰ì…˜ íƒ€ìž…ì˜ ë°ì´í„°ë¥¼ 반환하는 ì—°ì‚°ì‹ì€ ì§€ì •í• ìˆ˜ 없다. :param ALL: ëª¨ë“ ê°’ì— ëŒ€í•´ 최대 ê°’ì„ êµ¬í•˜ê¸° 위해 사용ë˜ë©°, 기본값ì´ë‹¤. :param DISTINCT,DISTINCTROW,UNIQUE: ì¤‘ë³µì´ ì œê±°ëœ ìœ ì¼í•œ ê°’ì— ëŒ€í•´ì„œ 최대 ê°’ì„ êµ¬í•˜ê¸° 위해 사용ëœë‹¤. :rtype: expressionì˜ íƒ€ìž… 다ìŒì€ 올림픽 대회 중 한êµì´ íšë“한 최대 ê¸ˆë©”ë‹¬ì˜ ìˆ˜ë¥¼ 반환하는 ì˜ˆì œì´ë‹¤. .. code-block:: sql SELECT MAX(gold) FROM participant WHERE nation_code = 'KOR'; :: max(gold) ============= 12 다ìŒì€ ì—대 올림픽 대회 중 êµê°€ 코드와 ì—°ë„ ìˆœëŒ€ë¡œ nation_codeê°€ 'AU'로 시작하는 êµê°€ê°€ íšë“한 금메달 수와 해당 êµê°€ì˜ ì—대 최대 ê¸ˆë©”ë‹¬ì˜ ìˆ˜ë¥¼ ê°™ì´ ì¶œë ¥í•˜ëŠ” ì˜ˆì œì´ë‹¤. .. code-block:: sql SELECT host_year, nation_code, gold, MAX(gold) OVER (PARTITION BY nation_code) mx_gold FROM participant WHERE nation_code LIKE 'AU%' ORDER BY nation_code, host_year; :: host_year nation_code gold mx_gold ============================================================= 1988 'AUS' 3 17 1992 'AUS' 7 17 1996 'AUS' 9 17 2000 'AUS' 16 17 2004 'AUS' 17 17 1988 'AUT' 1 2 1992 'AUT' 0 2 1996 'AUT' 0 2 2000 'AUT' 2 2 2004 'AUT' 2 2 MEDIAN ====== .. function:: MEDIAN(expression) .. function:: MEDIAN(expression) OVER ([<partition_by_clause>]) :noindex: **MEDIAN** 함수는 집계 함수 ë˜ëŠ” ë¶„ì„ í•¨ìˆ˜ë¡œ 사용ë˜ë©°, 중앙값(median value)ì„ ë°˜í™˜í•œë‹¤. ì¤‘ì•™ê°’ì€ ë°ì´í„°ì˜ 최소값과 ìµœëŒ€ê°’ì˜ ì¤‘ì•™ì— ìœ„ì¹˜í•˜ê²Œ ë˜ëŠ” ê°’ì„ ë§í•œë‹¤. :param expression: ìˆ«ìž ë˜ëŠ” ë‚ ì§œë¡œ 변환ë 수 있는 ê°’ì„ ê°€ì§„ 칼럼 ë˜ëŠ” ì—°ì‚°ì‹ :rtype: **DOUBLE** ë˜ëŠ” **DATETIME** 다ìŒì€ ì˜ˆì œ 질ì˜ë¥¼ 실행하기 위한 í…Œì´ë¸” 스키마 ë° ë°ì´í„°ì´ë‹¤. .. code-block:: sql CREATE TABLE tbl (col1 int, col2 double); INSERT INTO tbl VALUES(1,2), (1,1.5), (1,1.7), (1,1.8), (2,3), (2,4), (3,5); 다ìŒì€ 집계 함수로 사용ë˜ëŠ” 예로서, col1ì„ ê¸°ì¤€ìœ¼ë¡œ ê° ê·¸ë£¹ë³„ë¡œ 집계한 col2ì˜ ì¤‘ì•™ê°’ì„ ë°˜í™˜í•œë‹¤. .. code-block:: sql SELECT col1, MEDIAN(col2) FROM tbl GROUP BY col1; :: col1 median(col2) =================================== 1 1.750000000000000e+00 2 3.500000000000000e+00 3 5.000000000000000e+00 다ìŒì€ ë¶„ì„ í•¨ìˆ˜ë¡œ 사용ë˜ëŠ” 예로서, col1ì„ ê¸°ì¤€ìœ¼ë¡œ ê° ê·¸ë£¹ë³„ col2ì˜ ì¤‘ì•™ê°’ì„ ë°˜í™˜í•œë‹¤. .. code-block:: sql SELECT col1, MEDIAN(col2) OVER (PARTITION BY col1) FROM tbl; :: col1 median(col2) over (partition by col1) =================================== 1 1.750000000000000e+00 1 1.750000000000000e+00 1 1.750000000000000e+00 1 1.750000000000000e+00 2 3.500000000000000e+00 2 3.500000000000000e+00 3 5.000000000000000e+00 MIN === .. function:: MIN([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) .. function:: MIN([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) OVER (<analytic_clause>) :noindex: **MIN** 함수는 집계 함수 ë˜ëŠ” ë¶„ì„ í•¨ìˆ˜ë¡œ 사용ë˜ë©°, ëª¨ë“ í–‰ì— ëŒ€í•˜ì—¬ ì—°ì‚°ì‹ ê°’ 중 최소 ê°’ì„ êµ¬í•œë‹¤. í•˜ë‚˜ì˜ ì—°ì‚°ì‹ *expression* ë§Œ ì¸ìžë¡œ ì§€ì •ëœë‹¤. 문ìžì—´ì„ 반환하는 ì—°ì‚°ì‹ì— 대해서는 ì‚¬ì „ 순서를 기준으로 ì•žì— ë‚˜ì˜¤ëŠ” 문ìžì—´ì´ 최소 ê°’ì´ ë˜ê³ , 수치를 반환하는 ì—°ì‚°ì‹ì— 대해서는 í¬ê¸°ê°€ 가장 ìž‘ì€ ê°’ì´ ìµœì†Œ ê°’ì´ë‹¤. :param expression: 수치 ë˜ëŠ” 문ìžì—´ì„ 반환하는 í•˜ë‚˜ì˜ ì—°ì‚°ì‹ì„ ì§€ì •í•œë‹¤. ì»¬ë ‰ì…˜ íƒ€ìž…ì˜ ë°ì´í„°ë¥¼ 반환하는 ì—°ì‚°ì‹ì€ ì§€ì •í• ìˆ˜ 없다. :param ALL: ëª¨ë“ ê°’ì— ëŒ€í•´ 최소 ê°’ì„ êµ¬í•˜ê¸° 위해 사용ë˜ë©°, 기본값ì´ë‹¤. :param DISTINCT,DISTINCTROW,UNIQUE: ì¤‘ë³µì´ ì œê±°ëœ ìœ ì¼í•œ ê°’ì— ëŒ€í•´ì„œ 최소 ê°’ì„ êµ¬í•˜ê¸° 위해 사용ëœë‹¤. :rtype: expressionì˜ íƒ€ìž… 다ìŒì€ *demodb* ì—서 올림픽 대회 중 한êµì´ íšë“한 최소 ê¸ˆë©”ë‹¬ì˜ ìˆ˜ë¥¼ 반환하는 ì˜ˆì œì´ë‹¤. .. code-block:: sql SELECT MIN(gold) FROM participant WHERE nation_code = 'KOR'; :: min(gold) ============= 7 다ìŒì€ ì—대 올림픽 대회 중 êµê°€ 코드와 ì—°ë„ ìˆœëŒ€ë¡œ nation_codeê°€ 'AU'로 시작하는 êµê°€ê°€ íšë“한 금메달 수와 해당 êµê°€ì˜ ì—대 최소 ê¸ˆë©”ë‹¬ì˜ ìˆ˜ë¥¼ ê°™ì´ ì¶œë ¥í•˜ëŠ” ì˜ˆì œì´ë‹¤. .. code-block:: sql SELECT host_year, nation_code, gold, MIN(gold) OVER (PARTITION BY nation_code) mn_gold FROM participant WHERE nation_code like 'AU%' ORDER BY nation_code, host_year; :: host_year nation_code gold mn_gold ============================================================= 1988 'AUS' 3 3 1992 'AUS' 7 3 1996 'AUS' 9 3 2000 'AUS' 16 3 2004 'AUS' 17 3 1988 'AUT' 1 0 1992 'AUT' 0 0 1996 'AUT' 0 0 2000 'AUT' 2 0 2004 'AUT' 2 0 NTH_VALUE ========= .. function:: NTH_VALUE(expression, N) [{RESPECT|IGNORE} NULLS] OVER (<analytic_clause>) **NTH_VALUE** 함수는 ë¶„ì„ í•¨ìˆ˜ë¡œë§Œ 사용ë˜ë©°, ì •ë ¬ëœ ê°’ ì§‘í•©ì—서 *N*\ 번째 í–‰ì˜ *expression* ê°’ì„ ë°˜í™˜í•œë‹¤. :param expression: 수치 ë˜ëŠ” 문ìžì—´ì„ 반환하는 칼럼 ë˜ëŠ” ì—°ì‚°ì‹ :param N: ì–‘ì˜ ì •ìˆ˜ë¡œ í•´ì„ë 수 있는 ìƒìˆ˜, ë°”ì¸ë“œ 변수, 칼럼 ë˜ëŠ” í‘œí˜„ì‹ :rtype: *expression*\ ì˜ íƒ€ìž… .. seealso:: :func:`FIRST_VALUE`, :func:`LAST_VALUE` **{RESPECT|IGNORE} NULLS** êµ¬ë¬¸ì€ *expression*\ ì˜ null ê°’ì„ ê³„ì‚°ì— í¬í•¨ì‹œí‚¬ì§€ 여부를 ê²°ì •í•œë‹¤. ê¸°ë³¸ê°’ì€ **RESPECT NULLS**\ ì´ë‹¤. 다ìŒì€ ì˜ˆì œ 질ì˜ë¥¼ 실행하기 위한 스키마와 ë°ì´í„°ì´ë‹¤. .. code-block:: sql CREATE TABLE test_tbl(groupid int,itemno int); INSERT INTO test_tbl VALUES(1,null); INSERT INTO test_tbl VALUES(1,null); INSERT INTO test_tbl VALUES(1,1); INSERT INTO test_tbl VALUES(1,null); INSERT INTO test_tbl VALUES(1,2); INSERT INTO test_tbl VALUES(1,3); INSERT INTO test_tbl VALUES(1,4); INSERT INTO test_tbl VALUES(1,5); INSERT INTO test_tbl VALUES(2,null); INSERT INTO test_tbl VALUES(2,null); INSERT INTO test_tbl VALUES(2,null); INSERT INTO test_tbl VALUES(2,6); INSERT INTO test_tbl VALUES(2,7); 다ìŒì€ *N*\ ì˜ ê°’ì„ 2로 하여 **NTH_VALUE** 함수를 수행하는 ì§ˆì˜ ë° ê²°ê³¼ì´ë‹¤. .. code-block:: sql SELECT groupid, itemno, NTH_VALUE(itemno, 2) IGNORE NULLS OVER(PARTITION BY groupid ORDER BY itemno NULLS FIRST) AS ret_val FROM test_tbl; :: groupid itemno ret_val ======================================= 1 NULL NULL 1 NULL NULL 1 NULL NULL 1 1 NULL 1 2 2 1 3 2 1 4 2 1 5 2 2 NULL NULL 2 NULL NULL 2 NULL NULL 2 6 NULL 2 7 7 .. note:: CUBRID는 NULLì„ ëª¨ë“ ê°’ë³´ë‹¤ ì•žì˜ ìˆœì„œë¡œ ì •ë ¬í•œë‹¤. 즉, ì•„ëž˜ì˜ SQL1ì€ ORDER BY ì ˆì— NULLS FIRSTê°€ í¬í•¨ëœ SQL2로 í•´ì„ëœë‹¤. :: SQL1: NTH_VALUE(itemno) OVER(PARTITION BY groupid ORDER BY itemno) AS ret_val SQL2: NTH_VALUE(itemno) OVER(PARTITION BY groupid ORDER BY itemno NULLS FIRST) AS ret_val NTILE ===== .. function:: NTILE(expression) OVER ([<partition_by_clause>] <order_by_clause>) **NTILE** 함수는 ë¶„ì„ í•¨ìˆ˜ë¡œë§Œ 사용ë˜ë©°, 순차ì ì¸ ë°ì´í„° ì§‘í•©ì„ ìž…ë ¥ ì¸ìž ê°’ì— ì˜í•´ ì¼ë ¨ì˜ 버킷으로 나누며, ê° í–‰ì— ì 당한 버킷 번호를 1부터 í• ë‹¹í•œë‹¤. :param expression: ë²„í‚·ì˜ ê°œìˆ˜. ìˆ«ìž ê°’ì„ ë°˜í™˜í•˜ëŠ” ìž„ì˜ì˜ ì—°ì‚°ì‹ì„ ì§€ì •í•œë‹¤. :rtype: INT **NTILE** 함수는 주어진 버킷 개수로 í–‰ì˜ ê°œìˆ˜ë¥¼ ê· ë“±í•˜ê²Œ 나누어 버킷 번호를 부여한다. 즉, NTILE 함수는 equi-height histogramì„ ìƒì„±í•´ì¤€ë‹¤. ê° ë²„í‚·ì— ìžˆëŠ” í–‰ì˜ ê°œìˆ˜ëŠ” 최대 1개까지 ì°¨ì´ê°€ ìƒê¸¸ 수 있다. 나머지 ê°’(í–‰ì˜ ê°œìˆ˜ë¥¼ 버킷 개수로 나눈 나머지)ì´ ê° ë²„í‚·ì— ëŒ€í•´ 1번 버킷부터 하나씩 ë°°í¬ëœë‹¤. ë°˜ë©´ì— :func:`WIDTH_BUCKET` 함수는 주어진 버킷 개수로 주어진 범위를 ê· ë“±í•˜ê²Œ 나누어 버킷 번호를 부여한다. 즉, 버킷마다 ê° ë²”ìœ„ì˜ ë„“ì´ëŠ” ê· ë“±í•˜ë‹¤. 다ìŒì€ 8ëª…ì˜ ê³ ê°ì„ ìƒë…„ì›”ì¼ì„ 기준으로 5ê°œì˜ ë²„í‚·ìœ¼ë¡œ 나누ë˜, ê° ë²„í‚·ì˜ ìˆ˜ê°€ ê· ë“±í•˜ë„ë¡ ë‚˜ëˆ„ëŠ” 예ì´ë‹¤. 1, 2, 3번 버킷ì—는 2ê°œì˜ í–‰ì´, 4, 5번 버킷ì—는 2ê°œì˜ í–‰ì´ ì¡´ìž¬í•œë‹¤. .. code-block:: sql CREATE TABLE t_customer(name VARCHAR(10), birthdate DATE); INSERT INTO t_customer VALUES ('Amie', date'1978-03-18'), ('Jane', date'1983-05-12'), ('Lora', date'1987-03-26'), ('James', date'1948-12-28'), ('Peter', date'1988-10-25'), ('Tom', date'1980-07-28'), ('Ralph', date'1995-03-17'), ('David', date'1986-07-28'); SELECT name, birthdate, NTILE(5) OVER (ORDER BY birthdate) age_group FROM t_customer; :: name birthdate age_group =============================================== 'James' 12/28/1948 1 'Amie' 03/18/1978 1 'Tom' 07/28/1980 2 'Jane' 05/12/1983 2 'David' 07/28/1986 3 'Lora' 03/26/1987 3 'Peter' 10/25/1988 4 'Ralph' 03/17/1995 5 다ìŒì€ 8ëª…ì˜ í•™ìƒì„ ì 수가 ë†’ì€ ìˆœìœ¼ë¡œ 5ê°œì˜ ë²„í‚·ìœ¼ë¡œ 나눈 후, ì´ë¦„ 순으로 ì¶œë ¥í•˜ë˜, ê° ë²„í‚·ì˜ í–‰ì˜ ê°œìˆ˜ëŠ” ê· ë“±í•˜ê²Œ 나누는 예ì´ë‹¤. t_score í…Œì´ë¸”ì˜ score 칼럼ì—는 8ê°œì˜ í–‰ì´ ì¡´ìž¬í•˜ë¯€ë¡œ, 8ì„ 5로 나눈 나머지 3ê°œ í–‰ì´ 1번 버킷부터 ê°ê° í• ë‹¹ë˜ì–´ 1,2,3번 ë²„í‚·ì€ 4,5번 ë²„í‚·ì— ë¹„í•´ 1ê°œì˜ í–‰ì´ ë” ì¡´ìž¬í•œë‹¤. NTINE 함수는 ì ìˆ˜ì˜ ë²”ìœ„ì™€ëŠ” 무관하게 í–‰ì˜ ê°œìˆ˜ë¥¼ 기준으로 ê· ë“±í•˜ê²Œ grade를 나눈다. .. code-block:: sql CREATE TABLE t_score(name VARCHAR(10), score INT); INSERT INTO t_score VALUES ('Amie', 60), ('Jane', 80), ('Lora', 60), ('James', 75), ('Peter', 70), ('Tom', 30), ('Ralph', 99), ('David', 55); SELECT name, score, NTILE(5) OVER (ORDER BY score DESC) grade FROM t_score ORDER BY name; :: name score grade ================================================ 'Ralph' 99 1 'Jane' 80 1 'James' 75 2 'Peter' 70 2 'Amie' 60 3 'Lora' 60 3 'David' 55 4 'Tom' 30 5 PERCENT_RANK ============ .. function:: PERCENT_RANK(expression[, expression] ...) WITHIN GROUP (<order_by_clause>) .. function:: PERCENT_RANK() OVER ([<partition_by_clause>] <order_by_clause>) :noindex: PERCENT_RANK 함수는 집계 함수 ë˜ëŠ” ë¶„ì„ í•¨ìˆ˜ë¡œ 사용ë˜ë©°, 그룹ì—서 í–‰ì˜ ìƒëŒ€ì ì¸ ìœ„ì¹˜ë¥¼ 순위 í¼ì„¼íŠ¸ë¡œ 반환한다. CUME_DIST 함수(누ì ë¶„í¬ ê°’ì„ ë°˜í™˜)와 ìœ ì‚¬í•˜ë‹¤. PERCENT_RANKê°€ 반환하는 ê°’ì˜ ë²”ìœ„ëŠ” 0부터 1까지ì´ë‹¤. PERCENT_RANKì˜ ì²«ë²ˆì§¸ ê°’ì€ í•ìƒ 0ì´ë‹¤. :param expression: 수치 ë˜ëŠ” 문ìžì—´ì„ 반환하는 ì—°ì‚°ì‹. ì¹¼ëŸ¼ì´ ì˜¬ 수 없다. :rtype: DOUBLE .. seealso:: :func:`CUME_DIST`, :func:`RANK` 집계 í•¨ìˆ˜ì¸ ê²½ìš°, 집계 그룹 ì „ì²´ í–‰ì—서 ì„ íƒëœ ê°€ìƒ(hypothetical) í–‰ì˜ RANKì—서 1ì„ ëº€ ê°’ì— ëŒ€í•´ 집계 그룹 ë‚´ì˜ í–‰ì˜ ê°œìˆ˜ë¡œ 나눈 ê°’ì„ ë°˜í™˜í•œë‹¤. 즉, (ê°€ìƒ í–‰ì˜ RANK - 1)/(집계 그룹 í–‰ì˜ ê°œìˆ˜)를 반환한다. ë¶„ì„ í•¨ìˆ˜ì¸ ê²½ìš°, PARTITION BYì— ì˜í•´ 나누어진 그룹별로 ê° í–‰ì„ ORDER BY ì ˆì— ëª…ì‹œëœ ìˆœì„œë¡œ ì •ë ¬í–ˆì„ ë•Œ (그룹별 RANK - 1)/(그룹 í–‰ì˜ ê°œìˆ˜ - 1)ì„ ë°˜í™˜í•œë‹¤. 예를 들어, ì „ì²´ 10ê°œì˜ í–‰ 중ì—서 첫번째 순서(RANK=1)로 등장한 í–‰ì˜ ê°œìˆ˜ê°€ 2ê°œì´ë©´ 첫번째 행과 ë‘번째 í–‰ì˜ PERCENT_RANK ê°’ì€ (1-1)/(10-1)=0ì´ ëœë‹¤. .. _compare-cd-pr: 다ìŒì€ ìž…ë ¥ ê°’ VALì´ ì¡´ìž¬í• ë•Œ 집계 함수로 사용ë˜ëŠ” **CUME_DIST**\ 와 **PERCENT_RANK**\ ì˜ ë°˜í™˜ ê°’ì„ ë¹„êµí•œ 표ì´ë‹¤. ==================== ==================== ==================== ==================== ==================== VAL RANK() DENSE_RANK() CUME_DIST(VAL) PERCENT_RANK(VAL) ==================== ==================== ==================== ==================== ==================== 100 1 1 0.33 => (1+1)/(5+1) 0 => (1-1)/5 200 2 2 0.67 => (2+1)/(5+1) 0.2 => (2-1)/5 200 2 2 0.67 => (2+1)/(5+1) 0.2 => (2-1)/5 300 4 3 0.83 => (4+1)/(5+1) 0.6 => (4-1)/5 400 5 4 1 => (5+1)/(5+1) 0.8 => (5-1)/5 ==================== ==================== ==================== ==================== ==================== 다ìŒì€ ìž…ë ¥ ê°’ VALì´ ì¡´ìž¬í• ë•Œ ë¶„ì„ í•¨ìˆ˜ë¡œ 사용ë˜ëŠ” **CUME_DIST**\ 와 **PERCENT_RANK**\ ì˜ ë°˜í™˜ ê°’ì„ ë¹„êµí•œ 표ì´ë‹¤. ==================== ==================== ==================== ==================== ==================== VAL RANK() DENSE_RANK() CUME_DIST() PERCENT_RANK() ==================== ==================== ==================== ==================== ==================== 100 1 1 0.2 => 1/5 0 => (1-1)/(5-1) 200 2 2 0.6 => 3/5 0.25 => (2-1)/(5-1) 200 2 2 0.6 => 3/5 0.25 => (2-1)/(5-1) 300 4 3 0.8 => 4/5 0.75 => (4-1)/(5-1) 400 5 4 1 => 5/5 1 => (5-1)/(5-1) ==================== ==================== ==================== ==================== ==================== ìœ„ì˜ í‘œì™€ ê´€ë ¨ëœ ìŠ¤í‚¤ë§ˆ ë° ì§ˆì˜ì˜ 예는 다ìŒê³¼ 같다. .. code-block:: sql CREATE TABLE test_tbl(VAL INT); INSERT INTO test_tbl VALUES (100), (200), (200), (300), (400); SELECT CUME_DIST(100) WITHIN GROUP (ORDER BY val) AS cume FROM test_tbl; SELECT PERCENT_RANK(100) WITHIN GROUP (ORDER BY val) AS pct_rnk FROM test_tbl; SELECT CUME_DIST() OVER (ORDER BY val) AS cume FROM test_tbl; SELECT PERCENT_RANK() OVER (ORDER BY val) AS pct_rnk FROM test_tbl; 다ìŒì€ 아래ì—서 보여줄 질ì˜ì—서 ì‚¬ìš©ëœ ìŠ¤í‚¤ë§ˆ ë° ë°ì´í„°ì´ë‹¤. .. code-block:: sql CREATE TABLE scores(id INT PRIMARY KEY AUTO_INCREMENT, math INT, english INT, pe CHAR, grade INT); INSERT INTO scores(math, english, pe, grade) VALUES(60, 70, 'A', 1), (60, 70, 'A', 1), (60, 80, 'A', 1), (60, 70, 'B', 1), (70, 60, 'A', 1) , (70, 70, 'A', 1) , (80, 70, 'C', 1) , (70, 80, 'C', 1), (85, 60, 'C', 1), (75, 90, 'B', 1); INSERT INTO scores(math, english, pe, grade) VALUES(95, 90, 'A', 2), (85, 95, 'B', 2), (95, 90, 'A', 2), (85, 95, 'B', 2), (75, 80, 'D', 2), (75, 85, 'D', 2), (75, 70, 'C', 2), (65, 95, 'A', 2), (65, 95, 'A', 2), (65, 95, 'A', 2); 다ìŒì€ 집계 함수로 사용ë˜ëŠ” 예로, *math*, *english*, *pe* 3ê°œì˜ ì¹¼ëŸ¼ì— ëŒ€í•œ **PERCENT_RANK** ê°’ì„ ë”한 후 3으로 나눈 결과를 ì¶œë ¥í•œë‹¤. .. code-block:: sql SELECT PERCENT_RANK(60, 70, 'D') WITHIN GROUP(ORDER BY math, english, pe) AS percent_rank FROM scores; :: 1.500000000000000e-01 다ìŒì€ ë¶„ì„ í•¨ìˆ˜ë¡œ 사용ë˜ëŠ” 예로, *math*, *english*, *pe* 3ê°œ ì¹¼ëŸ¼ì„ ê¸°ì¤€ìœ¼ë¡œ í–‰ ì „ì²´ì˜ **PERCENT_RANK** ê°’ì„ ì¶œë ¥í•œë‹¤. .. code-block:: sql SELECT id, math, english, pe, grade, PERCENT_RANK() OVER(ORDER BY math, english, pe) AS percent_rank FROM scores ORDER BY percent_rank; :: id math english pe grade percent_rank ==================================================================================================== 1 60 70 'A' 1 0.000000000000000e+00 2 60 70 'A' 1 0.000000000000000e+00 4 60 70 'B' 1 1.052631578947368e-01 3 60 80 'A' 1 1.578947368421053e-01 18 65 95 'A' 2 2.105263157894737e-01 19 65 95 'A' 2 2.105263157894737e-01 20 65 95 'A' 2 2.105263157894737e-01 5 70 60 'A' 1 3.684210526315789e-01 6 70 70 'A' 1 4.210526315789473e-01 8 70 80 'C' 1 4.736842105263158e-01 17 75 70 'C' 2 5.263157894736842e-01 15 75 80 'D' 2 5.789473684210527e-01 16 75 85 'D' 2 6.315789473684210e-01 10 75 90 'B' 1 6.842105263157895e-01 7 80 70 'C' 1 7.368421052631579e-01 9 85 60 'C' 1 7.894736842105263e-01 12 85 95 'B' 2 8.421052631578947e-01 14 85 95 'B' 2 8.421052631578947e-01 11 95 90 'A' 2 9.473684210526315e-01 13 95 90 'A' 2 9.473684210526315e-01 다ìŒì€ ë¶„ì„ í•¨ìˆ˜ë¡œ 사용ë˜ëŠ” 예로, *math*, *english*, *pe* 3ê°œ ì¹¼ëŸ¼ì„ ê¸°ì¤€ìœ¼ë¡œ *grade* 칼럼으로 그룹핑하여 **PERCENT_RANK** ê°’ì„ ì¶œë ¥í•œë‹¤. .. code-block:: sql SELECT id, math, english, pe, grade, RANK(), PERCENT_RANK() OVER(PARTITION BY grade ORDER BY math, english, pe) AS percent_rank FROM scores ORDER BY grade, percent_rank; :: id math english pe grade percent_rank ==================================================================================================== 1 60 70 'A' 1 0.000000000000000e+00 2 60 70 'A' 1 0.000000000000000e+00 4 60 70 'B' 1 2.222222222222222e-01 3 60 80 'A' 1 3.333333333333333e-01 5 70 60 'A' 1 4.444444444444444e-01 6 70 70 'A' 1 5.555555555555556e-01 8 70 80 'C' 1 6.666666666666666e-01 10 75 90 'B' 1 7.777777777777778e-01 7 80 70 'C' 1 8.888888888888888e-01 9 85 60 'C' 1 1.000000000000000e+00 18 65 95 'A' 2 0.000000000000000e+00 19 65 95 'A' 2 0.000000000000000e+00 20 65 95 'A' 2 0.000000000000000e+00 17 75 70 'C' 2 3.333333333333333e-01 15 75 80 'D' 2 4.444444444444444e-01 16 75 85 'D' 2 5.555555555555556e-01 12 85 95 'B' 2 6.666666666666666e-01 14 85 95 'B' 2 6.666666666666666e-01 11 95 90 'A' 2 8.888888888888888e-01 13 95 90 'A' 2 8.888888888888888e-01 ìœ„ì˜ ê²°ê³¼ì—서 *id*\ ê°€ 1ì¸ í–‰ì€ *grade*\ ê°€ 1ì¸ 10ê°œì˜ í–‰ 중ì—서 첫번째와 ë‘ë²ˆì§¸ì— ìœ„ì¹˜í•˜ë©°, **PERCENT_RANK**\ ì˜ ê°’ì€ (1-1)/(10-1)=0ì´ ëœë‹¤. idê°€ 5ì¸ í–‰ì€ *grade*\ ê°€ 1ì¸ 10ê°œì˜ í–‰ 중ì—서 ë‹¤ì„¯ë²ˆì§¸ì— ìœ„ì¹˜í•˜ë©°, **PERCENT_RANK**\ ì˜ ê°’ì€ (5-1)/(10-1)=0.44ê°€ ëœë‹¤. PERCENTILE_CONT =============== .. function:: PERCENTILE_CONT(expression1) WITHIN GROUP (ORDER BY expression2 [ASC | DESC]) [OVER (<partition_by_clause>)] **PERCENTILE_CONT** 함수는 집계 함수 ë˜ëŠ” ë¶„ì„ í•¨ìˆ˜ë¡œ 사용ë˜ë©°, ì—°ì† ë¶„í¬(continuous distribution) 모ë¸ì„ ê°€ì •í•œ ì— ë¶„í¬ í•¨ìˆ˜ì´ë‹¤. 백분위 ê°’ì„ ìž…ë ¥ 받아 ì •ë ¬ëœ ê°’ë“¤ 중 ë°±ë¶„ìœ„ì— í•´ë‹¹í•˜ëŠ” ë³´ê°„ ê°’(interpolated value)ì„ ë°˜í™˜í•œë‹¤. 계산 시 NULL ê°’ì€ ë¬´ì‹œëœë‹¤. ì´ í•¨ìˆ˜ëŠ” ìž…ë ¥ ì¸ìžë¡œ 숫ìží˜• 타입 ë˜ëŠ” 숫ìžë¡œ 변환ë 수 있는 문ìžì—´ì´ 사용ë˜ë©°, 반환하는 ê°’ì˜ íƒ€ìž…ì€ DOUBLEì´ë‹¤. :param expression1: 백분위 ê°’. 0ê³¼ 1사ì´ì˜ 숫ìžì—¬ì•¼ 한다. :param expression2: ORDER BY ì ˆì— ë’¤ë”°ë¥´ëŠ” 칼럼 ì´ë¦„. 칼럼 개수는 *expression1*\ì˜ ì¹¼ëŸ¼ 개수와 ë™ì¼í•´ì•¼ 한다. :rtype: **DOUBLE** .. seealso:: :ref:`PERCENTILE_DISC와 PERCENTILE_CONT ì˜ ì°¨ì´ <compare-pd-pc>` 집계 í•¨ìˆ˜ì¸ ê²½ìš°, **PERCENTILE_DISC** 함수는 **ORDER BY** ì ˆì— ëª…ì‹œëœ ìˆœì„œë¡œ ê²°ê³¼ ê°’ì„ ì •ë ¬í•œ 후, 집계 ê·¸ë£¹ì— ìžˆëŠ” í–‰ì—서 ë°±ë¶„ìœ„ì— í•´ë‹¹í•˜ëŠ” ë³´ê°„ ê°’ì„ ë°˜í™˜í•œë‹¤. ë¶„ì„ í•¨ìˆ˜ì¸ ê²½ìš°, **PARTITION BY**\ ì— ì˜í•´ 나누어진 그룹별로 ê° í–‰ì„ **ORDER BY** ì ˆì— ëª…ì‹œëœ ìˆœì„œë¡œ ì •ë ¬í•œ 후, 그룹 ë‚´ì˜ í–‰ì—서 ë°±ë¶„ìœ„ì— í•´ë‹¹í•˜ëŠ” ë³´ê°„ ê°’ì„ ë°˜í™˜í•œë‹¤. .. _compare-pd-pc: .. note:: **PERCENTILE_CONT와 PERCENTILE_DISC ì˜ ì°¨ì´** PERCENTILE_CONT와 PERCENTILE_DISC는 다른 결과를 ë°˜í™˜í• ìˆ˜ 있다. PERCENTILE_CONT는 ì—°ì†ì ì¸ ë³´ê°„ì„ ìˆ˜í–‰í•œ ì´í›„ ê³„ì‚°ëœ ê²°ê³¼ë¥¼ 반환한다. PERCENTILE_DISC는 ì§‘ê³„ëœ ê°’ì˜ ì§‘í•©ìœ¼ë¡œë¶€í„° ê°’ì„ ë°˜í™˜í•œë‹¤. 아래 예ì—서 백분위 ê°’ì´ 0.5ì´ë©´ PERCENTILE_CONT 함수는 ì§ìˆ˜ ì›ì†Œë¥¼ 가진 ê·¸ë£¹ì— ëŒ€í•´ ë‘ ê°œì˜ ì¤‘ê°„ê°’ì˜ í‰ê· ì„ ë°˜í™˜í•˜ëŠ” 반면, PERCENTILEP_DISC 함수는 ë‘ ê°œì˜ ì¤‘ê°„ ê°’ 중 첫번째 ê°’ì„ ë°˜í™˜í•œë‹¤. 홀수 ê°œìˆ˜ì˜ ì›ì†Œë¥¼ 가진 집계 ê·¸ë£¹ì— ëŒ€í•´ì„œëŠ”, ë‘ í•¨ìˆ˜ ëª¨ë‘ ì¤‘ê°„ ì›ì†Œì˜ ê°’ì„ ë°˜í™˜í•œë‹¤. ì‹¤ì œë¡œ MEDIAN 함수는 기본 백분위수 ê°’(0.5)ì´ í¬í•¨ëœ PERCENTILE_CONTì˜ íŠ¹ìˆ˜í•œ 경우ì´ë‹¤. ìžì„¸í•œ ë‚´ìš©ì€ :func:`MEDIAN` ì„ ì°¸ê³ í•œë‹¤. 다ìŒì€ ì´ í•¨ìˆ˜ì˜ ì˜ˆì—서 사용ë 스키마 ë° ë°ì´í„°ì´ë‹¤. .. code-block:: sql CREATE TABLE scores([id] INT PRIMARY KEY AUTO_INCREMENT, [math] INT, english INT, [class] CHAR); INSERT INTO scores VALUES (1, 30, 70, 'A'), (2, 40, 70, 'A'), (3, 60, 80, 'A'), (4, 70, 70, 'A'), (5, 72, 60, 'A') , (6, 77, 70, 'A') , (7, 80, 70, 'C') , (8, 70, 80, 'C'), (9, 85, 60, 'C'), (10, 78, 90, 'B'), (11, 95, 90, 'D'), (12, 85, 95, 'B'), (13, 95, 90, 'B'), (14, 85, 95, 'B'), (15, 75, 80, 'D'), (16, 75, 85, 'D'), (17, 75, 70, 'C'), (18, 65, 95, 'C'), (19, 65, 95, 'D'), (20, 65, 95, 'D'); 다ìŒì€ 집계 함수로 사용ë˜ëŠ” 예로, *math* ì¹¼ëŸ¼ì— ëŒ€í•œ ì¤‘ì•™ê°’ì„ ì¶œë ¥í•œë‹¤. .. code-block:: sql SELECT PERCENTILE_CONT(0.5) WITHIN GROUP(ORDER BY math) AS pcont FROM scores; :: pcont ====================== 7.500000000000000e+01 다ìŒì€ ë¶„ì„ í•¨ìˆ˜ë¡œ 사용ë˜ëŠ” 예로, *class* ì¹¼ëŸ¼ì˜ ê°’ì´ ê°™ì€ ê²ƒë¼ë¦¬ 그룹핑한 ì§‘í•© ë‚´ì—서 *math* ì¹¼ëŸ¼ì— ëŒ€í•œ 중앙값(median)ì„ ì¶œë ¥í•œë‹¤. .. code-block:: sql SELECT math, [class], PERCENTILE_CONT(0.5) WITHIN GROUP(ORDER BY math) OVER (PARTITION BY [class]) AS pcont FROM scores; :: math class pcont ===================================================== 30 'A' 6.500000000000000e+01 40 'A' 6.500000000000000e+01 60 'A' 6.500000000000000e+01 70 'A' 6.500000000000000e+01 72 'A' 6.500000000000000e+01 77 'A' 6.500000000000000e+01 78 'B' 8.500000000000000e+01 85 'B' 8.500000000000000e+01 85 'B' 8.500000000000000e+01 95 'B' 8.500000000000000e+01 65 'C' 7.500000000000000e+01 70 'C' 7.500000000000000e+01 75 'C' 7.500000000000000e+01 80 'C' 7.500000000000000e+01 85 'C' 7.500000000000000e+01 65 'D' 7.500000000000000e+01 65 'D' 7.500000000000000e+01 75 'D' 7.500000000000000e+01 75 'D' 7.500000000000000e+01 95 'D' 7.500000000000000e+01 class 'A'ì—서 mathì˜ ê°’ì€ ì´ 6ê°œì¸ë°, PERCENTILE_CONT는 ì´ì‚° 값으로부터 ì—°ì†ëœ ê°’ì´ ì¡´ìž¬í•¨ì„ ê°€ì •í•˜ë¯€ë¡œ, ì¤‘ì•™ê°’ì€ 3번째 ê°’ 60ê³¼ 4번째 ê°’ 70ì˜ í‰ê· ì¸ 65ê°€ ëœë‹¤. PERCENTILE_CONT는 ì—°ì†ëœ ê°’ì„ ê°€ì •í•˜ë¯€ë¡œ ì—°ì†ëœ ê°’ì˜ í‘œí˜„ì´ ê°€ëŠ¥í•œ DOUBLE 타입으로 ë³€í™˜ëœ ê°’ì„ ì¶œë ¥í•œë‹¤. PERCENTILE_DISC =============== .. function:: PERCENTILE_DISC(expression1) WITHIN GROUP (ORDER BY expression2 [ASC | DESC]) [OVER (<partition_by_clause>)] **PERCENTILE_DISC** 함수는 집계 함수 ë˜ëŠ” ë¶„ì„ í•¨ìˆ˜ë¡œ 사용ë˜ë©°, ì´ì‚° ë¶„í¬(discrete distribution) 모ë¸ì„ ê°€ì •í•œ ì— ë¶„í¬ í•¨ìˆ˜ì´ë‹¤. 백분위 ê°’ì„ ìž…ë ¥ 받아 ì •ë ¬ëœ ê°’ë“¤ 중 ë°±ë¶„ìœ„ì— í•´ë‹¹í•˜ëŠ” ì´ì‚° ê°’(discrete value)ì„ ë°˜í™˜í•œë‹¤. 계산 시 NULL ê°’ì€ ë¬´ì‹œëœë‹¤. ì´ í•¨ìˆ˜ëŠ” ìž…ë ¥ ì¸ìžë¡œ 숫ìží˜• 타입 ë˜ëŠ” 숫ìžë¡œ 변환ë 수 있는 문ìžì—´ì´ 사용ë˜ë©°, 반환 íƒ€ìž…ì€ ìž…ë ¥ ê°’ì˜ íƒ€ìž…ê³¼ ë™ì¼í•˜ë‹¤. :param expression1: 백분위 ê°’. 0ê³¼ 1사ì´ì˜ 숫ìžì—¬ì•¼ 한다. :param expression2: ORDER BY ì ˆì— ë’¤ë”°ë¥´ëŠ” 칼럼 ì´ë¦„. 칼럼 개수는 *expression1*\ì˜ ì¹¼ëŸ¼ 개수와 ë™ì¼í•´ì•¼ 한다. :rtype: *expression2* ì˜ íƒ€ìž…ê³¼ ë™ì¼. .. seealso:: :ref:`PERCENTILE_DISC 와 PERCENTILE_CONT ì˜ ì°¨ì´ <compare-pd-pc>` 집계 í•¨ìˆ˜ì˜ ê²½ìš°, ì´ê²ƒì€ **ORDER BY** ì ˆì— ê¸°ìˆ ëœ ìˆœì„œë¡œ 결과를 ì •ë ¬í•œë‹¤; ê·¸ë¦¬ê³ ì§‘ê³„ ê·¸ë£¹ì— ìžˆëŠ” í–‰ì—서 ë°±ë¶„ìœ„ì— ìœ„ì¹˜í•œ ê°’ì„ ë°˜í™˜í•œë‹¤. ë¶„ì„ í•¨ìˆ˜ì¸ ê²½ìš°, **PARTITION BY**\ ì— ì˜í•´ 나누어진 그룹별로 ê° í–‰ì„ **ORDER BY** ì ˆì— ëª…ì‹œëœ ìˆœì„œë¡œ ì •ë ¬í•œ 후 그룹 ë‚´ì˜ í–‰ì—서 ë°±ë¶„ìœ„ì— ìœ„ì¹˜í•œ ê°’ì„ ë°˜í™˜í•œë‹¤. ì´ í•¨ìˆ˜ì˜ ì˜ˆì—서 ì‚¬ìš©ëœ ìŠ¤í‚¤ë§ˆì™€ ë°ì´í„°ëŠ” :func:`PERCENTILE_CONT`\ì—서 ì‚¬ìš©ëœ ê²ƒê³¼ ë™ì¼í•˜ë‹¤. 다ìŒì€ 집계 함수로 사용ë˜ëŠ” 예로, *math* ì¹¼ëŸ¼ì— ëŒ€í•œ 중앙값(median)ì„ ì¶œë ¥í•œë‹¤. .. code-block:: sql SELECT PERCENTILE_DISC(0.5) WITHIN GROUP(ORDER BY math) AS pdisc FROM scores; :: pdisc ====================== 75 다ìŒì€ ë¶„ì„ í•¨ìˆ˜ë¡œ 사용ë˜ëŠ” 예로, *class* ì¹¼ëŸ¼ì˜ ê°’ì´ ê°™ì€ ê²ƒë¼ë¦¬ 그룹핑한 ì§‘í•© ë‚´ì—서 *math* ì¹¼ëŸ¼ì— ëŒ€í•œ 중앙값(median)ì„ ì¶œë ¥í•œë‹¤. .. code-block:: sql SELECT math, [class], PERCENTILE_DISC(0.5) WITHIN GROUP(ORDER BY math) OVER (PARTITION BY [class]) AS pdisc FROM scores; :: math class pdisc ========================================================= 30 'A' 60 40 'A' 60 60 'A' 60 70 'A' 60 72 'A' 60 77 'A' 60 78 'B' 85 85 'B' 85 85 'B' 85 95 'B' 85 65 'C' 75 70 'C' 75 75 'C' 75 80 'C' 75 85 'C' 75 65 'D' 75 65 'D' 75 75 'D' 75 75 'D' 75 95 'D' 75 class 'A'ì—서 mathì˜ ê°’ì€ ì´ 6ê°œì¸ë°, PERCENTILE_DISC는 ì¤‘ê°„ì˜ ê°’ì´ ë‘ ê°œì¼ ë•Œ ì•žì˜ ê°’ì„ ì¶œë ¥í•˜ë¯€ë¡œ, ì¤‘ì•™ê°’ì€ 3번째 ê°’ 60ê³¼ 4번째 ê°’ 70 중 ì•žì˜ ê²ƒì¸ 60ì´ ëœë‹¤. RANK ==== .. function:: RANK() OVER ([<partition_by_clause>] <order_by_clause>) RANK 함수는 ë¶„ì„ í•¨ìˆ˜ë¡œë§Œ 사용ë˜ë©°, **PARTITION BY** ì ˆì— ì˜í•œ 칼럼 ê°’ì˜ ê·¸ë£¹ì—서 ê°’ì˜ ìˆœìœ„ë¥¼ 계산하여 **INTEGER** 로 ì¶œë ¥í•œë‹¤. ê³µë™ ìˆœìœ„ê°€ 존재하면 ê·¸ ë‹¤ìŒ ìˆœìœ„ëŠ” ê³µë™ ìˆœìœ„ì˜ ê°œìˆ˜ë¥¼ ë”한 숫ìžì´ë‹¤. 예를 들어, 13ìœ„ì— í•´ë‹¹í•˜ëŠ” í–‰ì´ 3ê°œì´ë©´ ê·¸ ë‹¤ìŒ í–‰ì˜ ìˆœìœ„ëŠ” 14위가 ì•„ë‹ˆë¼ 16위가 ëœë‹¤. 반면, :func:`DENSE_RANK` 함수는 ì´ì™€ 달리 ìˆœìœ„ì— 1ì„ ë”í•´ ë‹¤ìŒ ìˆœìœ„ì˜ ê°’ì„ ê³„ì‚°í•œë‹¤. :rtype: INT 다ìŒì€ ì—대 올림픽ì—서 ì—°ë„별로 ê¸ˆë©”ë‹¬ì„ ë§Žì´ íšë“한 êµê°€ì˜ 금메달 개수와 순위를 ì¶œë ¥í•˜ëŠ” ì˜ˆì œì´ë‹¤. ê³µë™ ìˆœìœ„ì˜ ë‹¤ìŒ ìˆœìœ„ ê°’ì€ ê³µë™ ìˆœìœ„ì˜ ê°œìˆ˜ë¥¼ ë”한다. .. code-block:: sql SELECT host_year, nation_code, gold, RANK() OVER (PARTITION BY host_year ORDER BY gold DESC) AS g_rank FROM participant; :: host_year nation_code gold g_rank ============================================================= 1988 'URS' 55 1 1988 'GDR' 37 2 1988 'USA' 36 3 1988 'KOR' 12 4 1988 'HUN' 11 5 1988 'FRG' 11 5 1988 'BUL' 10 7 1988 'ROU' 7 8 1988 'ITA' 6 9 1988 'FRA' 6 9 1988 'KEN' 5 11 1988 'GBR' 5 11 1988 'CHN' 5 11 ... 1988 'CHI' 0 32 1988 'ARG' 0 32 1988 'JAM' 0 32 1988 'SUI' 0 32 1988 'SWE' 0 32 1992 'EUN' 45 1 1992 'USA' 37 2 1992 'GER' 33 3 ... 2000 'RSA' 0 52 2000 'NGR' 0 52 2000 'JAM' 0 52 2000 'BRA' 0 52 2004 'USA' 36 1 2004 'CHN' 32 2 2004 'RUS' 27 3 2004 'AUS' 17 4 2004 'JPN' 16 5 2004 'GER' 13 6 2004 'FRA' 11 7 2004 'ITA' 10 8 2004 'UKR' 9 9 2004 'CUB' 9 9 2004 'GBR' 9 9 2004 'KOR' 9 9 ... 2004 'EST' 0 57 2004 'SLO' 0 57 2004 'SCG' 0 57 2004 'FIN' 0 57 2004 'POR' 0 57 2004 'MEX' 0 57 2004 'LAT' 0 57 2004 'PRK' 0 57 ROW_NUMBER ========== .. function:: ROW_NUMBER() OVER ([<partition_by_clause>] <order_by_clause>) **ROW_NUMBER** 함수는 ë¶„ì„ í•¨ìˆ˜ë¡œë§Œ 사용ë˜ë©°, **PARTITION BY** ì ˆì— ì˜í•œ 칼럼 ê°’ì˜ ê·¸ë£¹ì—서 ê° í–‰ì— ê³ ìœ í•œ ì¼ë ¨ë²ˆí˜¸ë¥¼ 1부터 순서대로 부여하여 **INTEGER** 로 ì¶œë ¥í•œë‹¤. :rtype: INT 다ìŒì€ ì—대 올림픽ì—서 ì—°ë„별로 ê¸ˆë©”ë‹¬ì„ ë§Žì´ íšë“한 êµê°€ì˜ 금메달 ê°œìˆ˜ì— ë”°ë¼ ì¼ë ¨ë²ˆí˜¸ë¥¼ ì¶œë ¥í•˜ë˜, 금메달 개수가 ê°™ì€ ê²½ìš°ì—는 nation_codeì˜ ì•ŒíŒŒë²³ 순서대로 ì¶œë ¥í•˜ëŠ” ì˜ˆì œì´ë‹¤. .. code-block:: sql SELECT host_year, nation_code, gold, ROW_NUMBER() OVER (PARTITION BY host_year ORDER BY gold DESC) AS r_num FROM participant; :: host_year nation_code gold r_num ============================================================= 1988 'URS' 55 1 1988 'GDR' 37 2 1988 'USA' 36 3 1988 'KOR' 12 4 1988 'FRG' 11 5 1988 'HUN' 11 6 1988 'BUL' 10 7 1988 'ROU' 7 8 1988 'FRA' 6 9 1988 'ITA' 6 10 1988 'CHN' 5 11 ... 1988 'YEM' 0 152 1988 'YMD' 0 153 1988 'ZAI' 0 154 1988 'ZAM' 0 155 1988 'ZIM' 0 156 1992 'EUN' 45 1 1992 'USA' 37 2 1992 'GER' 33 3 ... 2000 'VIN' 0 194 2000 'YEM' 0 195 2000 'ZAM' 0 196 2000 'ZIM' 0 197 2004 'USA' 36 1 2004 'CHN' 32 2 2004 'RUS' 27 3 2004 'AUS' 17 4 2004 'JPN' 16 5 2004 'GER' 13 6 2004 'FRA' 11 7 2004 'ITA' 10 8 2004 'CUB' 9 9 2004 'GBR' 9 10 2004 'KOR' 9 11 ... 2004 'UGA' 0 195 2004 'URU' 0 196 2004 'VAN' 0 197 2004 'VEN' 0 198 2004 'VIE' 0 199 2004 'VIN' 0 200 2004 'YEM' 0 201 2004 'ZAM' 0 202 STDDEV, STDDEV_POP ================== .. function:: STDDEV([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) .. function:: STDDEV_POP([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) :noindex: .. function:: STDDEV([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) OVER (<analytic_clause>) :noindex: .. function:: STDDEV_POP([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) OVER (<analytic_clause>) :noindex: **STDDEV** 함수와 **STDDEV_POP** 함수는 ë™ì¼í•˜ë©°, ì´ í•¨ìˆ˜ëŠ” 집계 함수 ë˜ëŠ” ë¶„ì„ í•¨ìˆ˜ë¡œ 사용ëœë‹¤. ì´ í•¨ìˆ˜ëŠ” ëª¨ë“ í–‰ì— ëŒ€í•œ ì—°ì‚°ì‹ ê°’ë“¤ì— ëŒ€í•œ 표준편차, 즉 모표준 편차를 반환한다. **STDDEV_POP** 함수가 SQL:1999 표준ì´ë‹¤. í•˜ë‚˜ì˜ ì—°ì‚°ì‹ *expression* ë§Œ ì¸ìžë¡œ ì§€ì •ë˜ë©°, ì—°ì‚°ì‹ ì•žì— **DISTINCT** ë˜ëŠ” **UNIQUE** 키워드를 í¬í•¨ì‹œí‚¤ë©´ ì—°ì‚°ì‹ ê°’ 중 ì¤‘ë³µì„ ì œê±°í•œ 후, 모표준 편차를 êµ¬í•˜ê³ , 키워드가 ìƒëžµë˜ê±°ë‚˜ **ALL** ì¸ ê²½ìš°ì—는 ëª¨ë“ ê°’ì— ëŒ€í•´ 모표준 편차를 구한다. :param expression: 수치를 반환하는 í•˜ë‚˜ì˜ ì—°ì‚°ì‹ì„ ì§€ì •í•œë‹¤. :param ALL: ëª¨ë“ ê°’ì— ëŒ€í•´ 표준 편차를 구하기 위해 사용ë˜ë©°, 기본값ì´ë‹¤. :param DISTINCT,DISTINCTROW,UNIQUE: ì¤‘ë³µì´ ì œê±°ëœ ìœ ì¼í•œ ê°’ì— ëŒ€í•´ì„œë§Œ 표준 편차를 구하기 위해 사용ëœë‹¤. :rtype: DOUBLE 리턴 ê°’ì€ :func:`VAR_POP` 리턴 ê°’ì˜ ì œê³±ê·¼ê³¼ 같으며 **DOUBLE** 타입ì´ë‹¤. ê²°ê³¼ ê³„ì‚°ì— ì‚¬ìš©í• í–‰ì´ ì—†ìœ¼ë©´ **NULL** ì„ ë°˜í™˜í•œë‹¤. 다ìŒì€ í•¨ìˆ˜ì— ì ìš©ëœ ê³µì‹ì´ë‹¤. .. (TODO - equation) .. image:: /images/stddev_pop.jpg .. warning:: CUBRID 2008 R3.1 ì´í•˜ ë²„ì „ì—서 **STDDEV** 함수는 :func:`STDDEV_SAMP` 와 ê°™ì€ ê¸°ëŠ¥ì„ ìˆ˜í–‰í–ˆë‹¤. 다ìŒì€ ì „ì²´ ê³¼ëª©ì— ëŒ€í•´ ì „ì²´ í•™ìƒì˜ 모표준 편차를 ì¶œë ¥í•˜ëŠ” ì˜ˆì œì´ë‹¤. .. code-block:: sql CREATE TABLE student (name VARCHAR(32), subjects_id INT, score DOUBLE); INSERT INTO student VALUES ('Jane',1, 78), ('Jane',2, 50), ('Jane',3, 60), ('Bruce', 1, 63), ('Bruce', 2, 50), ('Bruce', 3, 80), ('Lee', 1, 85), ('Lee', 2, 88), ('Lee', 3, 93), ('Wane', 1, 32), ('Wane', 2, 42), ('Wane', 3, 99), ('Sara', 1, 17), ('Sara', 2, 55), ('Sara', 3, 43); SELECT STDDEV_POP (score) FROM student; :: stddev_pop(score) ========================== 2.329711474744362e+01 다ìŒì€ ê° ê³¼ëª©(subjects_id)별로 ì „ì²´ í•™ìƒì˜ ì 수와 모표준 편차를 함께 ì¶œë ¥í•˜ëŠ” ì˜ˆì œì´ë‹¤. .. code-block:: sql SELECT subjects_id, name, score, STDDEV_POP(score) OVER(PARTITION BY subjects_id) std_pop FROM student ORDER BY subjects_id, name; :: subjects_id name score std_pop ======================================================================================= 1 'Bruce' 6.300000000000000e+01 2.632869157402243e+01 1 'Jane' 7.800000000000000e+01 2.632869157402243e+01 1 'Lee' 8.500000000000000e+01 2.632869157402243e+01 1 'Sara' 1.700000000000000e+01 2.632869157402243e+01 1 'Wane' 3.200000000000000e+01 2.632869157402243e+01 2 'Bruce' 5.000000000000000e+01 1.604992211819110e+01 2 'Jane' 5.000000000000000e+01 1.604992211819110e+01 2 'Lee' 8.800000000000000e+01 1.604992211819110e+01 2 'Sara' 5.500000000000000e+01 1.604992211819110e+01 2 'Wane' 4.200000000000000e+01 1.604992211819110e+01 3 'Bruce' 8.000000000000000e+01 2.085185843036539e+01 3 'Jane' 6.000000000000000e+01 2.085185843036539e+01 3 'Lee' 9.300000000000000e+01 2.085185843036539e+01 3 'Sara' 4.300000000000000e+01 2.085185843036539e+01 3 'Wane' 9.900000000000000e+01 2.085185843036539e+01 STDDEV_SAMP =========== .. function:: STDDEV_SAMP([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) .. function:: STDDEV_SAMP([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) OVER (<analytic_clause>) :noindex: **STDDEV_SAMP** 함수는 집계 함수 ë˜ëŠ” ë¶„ì„ í•¨ìˆ˜ë¡œ 사용ë˜ë©°, 표본 표준편차를 구한다. í•˜ë‚˜ì˜ ì—°ì‚°ì‹ *expression* ë§Œ ì¸ìžë¡œ ì§€ì •ë˜ë©°, ì—°ì‚°ì‹ ì•žì— **DISTINCT** ë˜ëŠ” **UNIQUE** 키워드를 í¬í•¨ì‹œí‚¤ë©´ ì—°ì‚°ì‹ ê°’ 중 ì¤‘ë³µì„ ì œê±°í•œ 후, 표본 표준편차를 êµ¬í•˜ê³ , 키워드가 ìƒëžµë˜ê±°ë‚˜ **ALL** ì¸ ê²½ìš°ì—는 ëª¨ë“ ê°’ì— ëŒ€í•´ 표본 표준편차를 구한다. :param expression: 수치를 반환하는 í•˜ë‚˜ì˜ ì—°ì‚°ì‹ì„ ì§€ì •í•œë‹¤. :param ALL: ëª¨ë“ ê°’ì— ëŒ€í•´ 표준 편차를 구하기 위해 사용ë˜ë©°, 기본값ì´ë‹¤. :param DISTINCT,DISTINCTROW,UNIQUE: ì¤‘ë³µì´ ì œê±°ëœ ìœ ì¼í•œ ê°’ì— ëŒ€í•´ì„œë§Œ 표준 편차를 구하기 위해 사용ëœë‹¤. :rtype: DOUBLE 리턴 ê°’ì€ :func:`VAR_SAMP` 리턴 ê°’ì˜ ì œê³±ê·¼ê³¼ 같으며 **DOUBLE** 타입ì´ë‹¤. ê²°ê³¼ ê³„ì‚°ì— ì‚¬ìš©í• í–‰ì´ ì—†ìœ¼ë©´ **NULL** ì„ ë°˜í™˜í•œë‹¤. 다ìŒì€ í•¨ìˆ˜ì— ì ìš©ëœ ê³µì‹ì´ë‹¤. .. (TODO - equation) .. image:: /images/stddev_samp.jpg 다ìŒì€ ì „ì²´ ê³¼ëª©ì— ëŒ€í•´ ì „ì²´ í•™ìƒì˜ 표본 표준 편차를 ì¶œë ¥í•˜ëŠ” ì˜ˆì œì´ë‹¤. .. code-block:: sql CREATE TABLE student (name VARCHAR(32), subjects_id INT, score DOUBLE); INSERT INTO student VALUES ('Jane',1, 78), ('Jane',2, 50), ('Jane',3, 60), ('Bruce', 1, 63), ('Bruce', 2, 50), ('Bruce', 3, 80), ('Lee', 1, 85), ('Lee', 2, 88), ('Lee', 3, 93), ('Wane', 1, 32), ('Wane', 2, 42), ('Wane', 3, 99), ('Sara', 1, 17), ('Sara', 2, 55), ('Sara', 3, 43); SELECT STDDEV_SAMP (score) FROM student; :: stddev_samp(score) ========================== 2.411480477888654e+01 다ìŒì€ ê° ê³¼ëª©(subjects_id)별로 ì „ì²´ í•™ìƒì˜ ì 수와 표본 표준편차를 함께 ì¶œë ¥í•˜ëŠ” ì˜ˆì œì´ë‹¤. .. code-block:: sql SELECT subjects_id, name, score, STDDEV_SAMP(score) OVER(PARTITION BY subjects_id) std_samp FROM student ORDER BY subjects_id, name; :: subjects_id name score std_samp ======================================================================================= 1 'Bruce' 6.300000000000000e+01 2.943637205907005e+01 1 'Jane' 7.800000000000000e+01 2.943637205907005e+01 1 'Lee' 8.500000000000000e+01 2.943637205907005e+01 1 'Sara' 1.700000000000000e+01 2.943637205907005e+01 1 'Wane' 3.200000000000000e+01 2.943637205907005e+01 2 'Bruce' 5.000000000000000e+01 1.794435844492636e+01 2 'Jane' 5.000000000000000e+01 1.794435844492636e+01 2 'Lee' 8.800000000000000e+01 1.794435844492636e+01 2 'Sara' 5.500000000000000e+01 1.794435844492636e+01 2 'Wane' 4.200000000000000e+01 1.794435844492636e+01 3 'Bruce' 8.000000000000000e+01 2.331308645374953e+01 3 'Jane' 6.000000000000000e+01 2.331308645374953e+01 3 'Lee' 9.300000000000000e+01 2.331308645374953e+01 3 'Sara' 4.300000000000000e+01 2.331308645374953e+01 3 'Wane' 9.900000000000000e+01 2.331308645374953e+01 SUM === .. function:: SUM ( [ DISTINCT | DISTINCTROW | UNIQUE | ALL ] expression ) .. function:: SUM ( [ DISTINCT | DISTINCTROW | UNIQUE | ALL ] expression ) OVER (<analytic_clause>) :noindex: **SUM** 함수는 집계 함수 ë˜ëŠ” ë¶„ì„ í•¨ìˆ˜ë¡œ 사용ë˜ë©°, ëª¨ë“ í–‰ì— ëŒ€í•œ ì—°ì‚°ì‹ ê°’ë“¤ì˜ í•©ê³„ë¥¼ 반환한다. í•˜ë‚˜ì˜ ì—°ì‚°ì‹ *expression* ë§Œ ì¸ìžë¡œ ì§€ì •ë˜ë©°, ì—°ì‚°ì‹ ì•žì— **DISTINCT** ë˜ëŠ” **UNIQUE** 키워드를 í¬í•¨ì‹œí‚¤ë©´ ì—°ì‚°ì‹ ê°’ 중 ì¤‘ë³µì„ ì œê±°í•œ 후 합계를 êµ¬í•˜ê³ , 키워드가 ìƒëžµë˜ê±°ë‚˜ **ALL** ì¸ ê²½ìš°ì—는 ëª¨ë“ ê°’ì— ëŒ€í•´ 합계를 구한다. ë‹¨ì¼ ê°’ 수ì‹ì„ **SUM** í•¨ìˆ˜ì˜ ìž…ë ¥ìœ¼ë¡œ ì‚¬ìš©í• ìˆ˜ 있다. :param expression: 수치를 반환하는 í•˜ë‚˜ì˜ ì—°ì‚°ì‹ì„ ì§€ì •í•œë‹¤. :param ALL: ëª¨ë“ ê°’ì— ëŒ€í•´ 합계를 구하기 위해 사용ë˜ë©°, 기본으로 ì§€ì •ëœë‹¤. :param DISTINCT,DISTICNTROW,UNIQUE: ì¤‘ë³µì´ ì œê±°ëœ ìœ ì¼í•œ ê°’ì— ëŒ€í•´ì„œë§Œ 합계를 구하기 위해 사용ëœë‹¤. :rtype: expressionì˜ íƒ€ìž… 다ìŒì€ *demodb* ì—서 ì—대 올림픽ì—서 íšë“한 금메달 ìˆ˜ì˜ í•©ê³„ë¥¼ 기준으로 10위권 êµê°€ì™€ 금메달 ì´ ìˆ˜ë¥¼ ì¶œë ¥í•˜ëŠ” ì˜ˆì œì´ë‹¤. .. code-block:: sql SELECT nation_code, SUM(gold) FROM participant GROUP BY nation_code ORDER BY SUM(gold) DESC LIMIT 10; :: nation_code sum(gold) =================================== 'USA' 190 'CHN' 97 'RUS' 85 'GER' 79 'URS' 55 'FRA' 53 'AUS' 52 'ITA' 48 'KOR' 48 'EUN' 45 다ìŒì€ *demodb* ì—서 nation_codeê°€ 'AU'로 시작하는 êµê°€ì— 대해 ì—°ë„별로 íšë“한 금메달 수와 해당 ì—°ë„ê¹Œì§€ì˜ ê¸ˆë©”ë‹¬ 누ì 합계를 ì¶œë ¥í•˜ëŠ” ì˜ˆì œì´ë‹¤. .. code-block:: sql SELECT host_year, nation_code, gold, SUM(gold) OVER (PARTITION BY nation_code ORDER BY host_year) sum_gold FROM participant WHERE nation_code LIKE 'AU%'; :: host_year nation_code gold sum_gold ============================================================= 1988 'AUS' 3 3 1992 'AUS' 7 10 1996 'AUS' 9 19 2000 'AUS' 16 35 2004 'AUS' 17 52 1988 'AUT' 1 1 1992 'AUT' 0 1 1996 'AUT' 0 1 2000 'AUT' 2 3 2004 'AUT' 2 5 다ìŒì€ 위 ì˜ˆì œì—서 **OVER** 함수 ì´í•˜ì˜ "ORDER BY host_year" ì ˆì„ ì œê±°í•œ 것으로, sum_goldì˜ ê°’ì€ ëª¨ë“ ì—°ë„ì˜ ê¸ˆë©”ë‹¬ 합계로 ê° ì—°ë„ì—서 ëª¨ë‘ ê°™ì€ ê°’ì„ ê°€ì§„ë‹¤. .. code-block:: sql SELECT host_year, nation_code, gold, SUM(gold) OVER (PARTITION BY nation_code) sum_gold FROM participant WHERE nation_code LIKE 'AU%'; :: host_year nation_code gold sum_gold ============================================================= 2004 'AUS' 17 52 2000 'AUS' 16 52 1996 'AUS' 9 52 1992 'AUS' 7 52 1988 'AUS' 3 52 2004 'AUT' 2 5 2000 'AUT' 2 5 1996 'AUT' 0 5 1992 'AUT' 0 5 1988 'AUT' 1 5 VARIANCE, VAR_POP ================= .. function:: VARIANCE([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) .. function:: VAR_POP([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) .. function:: VARIANCE([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) OVER (<analytic_clause>) :noindex: .. function:: VAR_POP([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) OVER (<analytic_clause>) :noindex: **VARIANCE** 함수와 **VAR_POP** 함수는 ë™ì¼í•˜ë©°, 집계 함수 ë˜ëŠ” ë¶„ì„ í•¨ìˆ˜ë¡œ 사용ëœë‹¤. ì´ í•¨ìˆ˜ëŠ” ëª¨ë“ í–‰ì— ëŒ€í•œ ì—°ì‚°ì‹ ê°’ë“¤ì— ëŒ€í•œ ë¶„ì‚°, 즉 ëª¨ë¶„ì‚°ì„ ë°˜í™˜í•œë‹¤. 분모는 ëª¨ë“ í–‰ì˜ ê°œìˆ˜ì´ë‹¤. í•˜ë‚˜ì˜ ì—°ì‚°ì‹ *expression* ë§Œ ì¸ìžë¡œ ì§€ì •ë˜ë©°, ì—°ì‚°ì‹ ì•žì— **DISTINCT** ë˜ëŠ” **UNIQUE** 키워드를 í¬í•¨ì‹œí‚¤ë©´ ì—°ì‚°ì‹ ê°’ 중 ì¤‘ë³µì„ ì œê±°í•œ 후, ëª¨ë¶„ì‚°ì„ êµ¬í•˜ê³ , 키워드가 ìƒëžµë˜ê±°ë‚˜ **ALL** ì¸ ê²½ìš°ì—는 ëª¨ë“ ê°’ì— ëŒ€í•´ ëª¨ë¶„ì‚°ì„ êµ¬í•œë‹¤. :param expression: 수치를 반환하는 í•˜ë‚˜ì˜ ì—°ì‚°ì‹ì„ ì§€ì •í•œë‹¤. :param ALL: ëª¨ë“ ê°’ì— ëŒ€í•´ ëª¨ë¶„ì‚°ì„ êµ¬í•˜ê¸° 위해 사용ë˜ë©°, 기본값ì´ë‹¤. :param DISTINCT,DISTINCTROW,UNIQUE: ì¤‘ë³µì´ ì œê±°ëœ ìœ ì¼í•œ ê°’ì— ëŒ€í•´ì„œë§Œ ëª¨ë¶„ì‚°ì„ êµ¬í•˜ê¸° 위해 사용ëœë‹¤. :rtype: DOUBLE 리턴 ê°’ì€ **DOUBLE** 타입ì´ë©°, ê²°ê³¼ ê³„ì‚°ì— ì‚¬ìš©í• í–‰ì´ ì—†ìœ¼ë©´ **NULL** ì„ ë°˜í™˜í•œë‹¤. 다ìŒì€ í•¨ìˆ˜ì— ì ìš©ëœ ê³µì‹ì´ë‹¤. .. image:: /images/var_pop.jpg .. note:: CUBRID 2008 R3.1 ì´í•˜ ë²„ì „ì—서 **VARIANCE** 함수는 :func:`VAR_SAMP`\ 와 ê°™ì€ ê¸°ëŠ¥ì„ ìˆ˜í–‰í–ˆë‹¤. 다ìŒì€ ì „ì²´ ê³¼ëª©ì— ëŒ€í•´ ì „ì²´ í•™ìƒì˜ ëª¨ë¶„ì‚°ì„ ì¶œë ¥í•˜ëŠ” ì˜ˆì œì´ë‹¤. .. code-block:: sql CREATE TABLE student (name VARCHAR(32), subjects_id INT, score DOUBLE); INSERT INTO student VALUES ('Jane',1, 78), ('Jane',2, 50), ('Jane',3, 60), ('Bruce', 1, 63), ('Bruce', 2, 50), ('Bruce', 3, 80), ('Lee', 1, 85), ('Lee', 2, 88), ('Lee', 3, 93), ('Wane', 1, 32), ('Wane', 2, 42), ('Wane', 3, 99), ('Sara', 1, 17), ('Sara', 2, 55), ('Sara', 3, 43); SELECT VAR_POP(score) FROM student; :: var_pop(score) ========================== 5.427555555555550e+02 다ìŒì€ ê° ê³¼ëª©(subjects_id)별로 ì „ì²´ í•™ìƒì˜ ì 수와 ëª¨ë¶„ì‚°ì„ í•¨ê»˜ ì¶œë ¥í•˜ëŠ” ì˜ˆì œì´ë‹¤. .. code-block:: sql SELECT subjects_id, name, score, VAR_POP(score) OVER(PARTITION BY subjects_id) v_pop FROM student ORDER BY subjects_id, name; :: subjects_id name score v_pop ======================================================================================= 1 'Bruce' 6.300000000000000e+01 6.931999999999998e+02 1 'Jane' 7.800000000000000e+01 6.931999999999998e+02 1 'Lee' 8.500000000000000e+01 6.931999999999998e+02 1 'Sara' 1.700000000000000e+01 6.931999999999998e+02 1 'Wane' 3.200000000000000e+01 6.931999999999998e+02 2 'Bruce' 5.000000000000000e+01 2.575999999999999e+02 2 'Jane' 5.000000000000000e+01 2.575999999999999e+02 2 'Lee' 8.800000000000000e+01 2.575999999999999e+02 2 'Sara' 5.500000000000000e+01 2.575999999999999e+02 2 'Wane' 4.200000000000000e+01 2.575999999999999e+02 3 'Bruce' 8.000000000000000e+01 4.348000000000002e+02 3 'Jane' 6.000000000000000e+01 4.348000000000002e+02 3 'Lee' 9.300000000000000e+01 4.348000000000002e+02 3 'Sara' 4.300000000000000e+01 4.348000000000002e+02 3 'Wane' 9.900000000000000e+01 4.348000000000002e+02 VAR_SAMP ======== .. function:: VAR_SAMP([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) .. function:: VAR_SAMP([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) OVER (<analytic_clause>) :noindex: **VAR_SAMP** 함수는 집계 함수 ë˜ëŠ” ë¶„ì„ í•¨ìˆ˜ë¡œ 사용ë˜ë©°, 표본 ë¶„ì‚°ì„ ë°˜í™˜í•œë‹¤. 분모는 ëª¨ë“ í–‰ì˜ ê°œìˆ˜ - 1ì´ë‹¤. í•˜ë‚˜ì˜ *expression*\ ë§Œ ì¸ìžë¡œ ì§€ì •ë˜ë©°, *expression* ì•žì— **DISTINCT** ë˜ëŠ” **UNIQUE** 키워드를 í¬í•¨ì‹œí‚¤ë©´ ì—°ì‚°ì‹ ê°’ 중 ì¤‘ë³µì„ ì œê±°í•œ 후, 표본 ë¶„ì‚°ì„ êµ¬í•˜ê³ , 키워드가 ìƒëžµë˜ê±°ë‚˜ **ALL** ì¸ ê²½ìš°ì—는 ëª¨ë“ ê°’ì— ëŒ€í•´ 표본 ë¶„ì‚°ì„ êµ¬í•œë‹¤. :param expression: 수치를 반환하는 í•˜ë‚˜ì˜ ì—°ì‚°ì‹ì„ ì§€ì •í•œë‹¤. :param ALL: ëª¨ë“ ê°’ì— ëŒ€í•´ 표본 ë¶„ì‚°ì„ êµ¬í•˜ê¸° 위해 사용ë˜ë©°, 기본값ì´ë‹¤. :param DISTINCT,DISTINCTROW,UNIQUE: ì¤‘ë³µì´ ì œê±°ëœ ìœ ì¼í•œ ê°’ì— ëŒ€í•´ì„œë§Œ 표본 ë¶„ì‚°ì„ êµ¬í•˜ê¸° 위해 사용ëœë‹¤. :rtype: DOUBLE 리턴 ê°’ì€ **DOUBLE** 타입ì´ë©°, ê²°ê³¼ ê³„ì‚°ì— ì‚¬ìš©í• í–‰ì´ ì—†ìœ¼ë©´ **NULL** ì„ ë°˜í™˜í•œë‹¤. 다ìŒì€ í•¨ìˆ˜ì— ì ìš©ëœ ê³µì‹ì´ë‹¤. .. image:: /images/var_samp.jpg 다ìŒì€ ì „ì²´ ê³¼ëª©ì— ëŒ€í•´ ì „ì²´ í•™ìƒì˜ 표본 ë¶„ì‚°ì„ ì¶œë ¥í•˜ëŠ” ì˜ˆì œì´ë‹¤. .. code-block:: sql CREATE TABLE student (name VARCHAR(32), subjects_id INT, score DOUBLE); INSERT INTO student VALUES ('Jane',1, 78), ('Jane',2, 50), ('Jane',3, 60), ('Bruce', 1, 63), ('Bruce', 2, 50), ('Bruce', 3, 80), ('Lee', 1, 85), ('Lee', 2, 88), ('Lee', 3, 93), ('Wane', 1, 32), ('Wane', 2, 42), ('Wane', 3, 99), ('Sara', 1, 17), ('Sara', 2, 55), ('Sara', 3, 43); SELECT VAR_SAMP(score) FROM student; :: var_samp(score) ========================== 5.815238095238092e+02 다ìŒì€ ê° ê³¼ëª©(subjects_id)별로 ì „ì²´ í•™ìƒì˜ ì 수와 표본 ë¶„ì‚°ì„ í•¨ê»˜ ì¶œë ¥í•˜ëŠ” ì˜ˆì œì´ë‹¤. .. code-block:: sql SELECT subjects_id, name, score, VAR_SAMP(score) OVER(PARTITION BY subjects_id) v_samp FROM student ORDER BY subjects_id, name; :: subjects_id name score v_samp ======================================================================================= 1 'Bruce' 6.300000000000000e+01 8.665000000000000e+02 1 'Jane' 7.800000000000000e+01 8.665000000000000e+02 1 'Lee' 8.500000000000000e+01 8.665000000000000e+02 1 'Sara' 1.700000000000000e+01 8.665000000000000e+02 1 'Wane' 3.200000000000000e+01 8.665000000000000e+02 2 'Bruce' 5.000000000000000e+01 3.220000000000000e+02 2 'Jane' 5.000000000000000e+01 3.220000000000000e+02 2 'Lee' 8.800000000000000e+01 3.220000000000000e+02 2 'Sara' 5.500000000000000e+01 3.220000000000000e+02 2 'Wane' 4.200000000000000e+01 3.220000000000000e+02 3 'Bruce' 8.000000000000000e+01 5.435000000000000e+02 3 'Jane' 6.000000000000000e+01 5.435000000000000e+02 3 'Lee' 9.300000000000000e+01 5.435000000000000e+02 3 'Sara' 4.300000000000000e+01 5.435000000000000e+02 3 'Wane' 9.900000000000000e+01 5.435000000000000e+02 .. _fn-json-arrayagg: JSON_ARRAYAGG =================================== .. function:: JSON_ARRAYAGG (json_val) í‰ê°€ëœ 행으로부터 JSON ë°°ì—´ì„ ë§Œë“œëŠ” 집계 함수ì´ë‹¤. .. code-block:: sql CREATE TABLE t_score(name VARCHAR(10), score INT); INSERT INTO t_score VALUES ('Amie', 60), ('Jane', 80), ('Lora', 60), ('James', 75), ('Peter', 70), ('Tom', 30), ('Ralph', 99), ('David', 55), ('Amie', 65); SELECT JSON_ARRAYAGG (name) AS test_takers from t_score; :: test_takers ====================== ["Amie","Jane","Lora","James","Peter","Tom","Ralph","David","Amie"] .. _fn-json-objectagg: JSON_OBJECTAGG =================================== .. function:: JSON_OBJECTYAGG (key, json_val expr) ê° í–‰ì˜ í‰ê°€ì—서 ìˆ˜ì§‘ëœ (key, json_val) 표현ì‹ìœ¼ë¡œë¶€í„° JSON ê°ì²´ë¥¼ ìƒì„±í•œë‹¤. .. code-block:: sql CREATE TABLE t_score(name VARCHAR(10), score INT); INSERT INTO t_score VALUES ('Amie', 60), ('Jane', 80), ('Lora', 60), ('James', 75), ('Peter', 70), ('Tom', 30), ('Ralph', 99), ('David', 55); SELECT JSON_OBJECTAGG (name, score) AS test_scores from t_score; :: test_scores ====================== {"Amie":60,"Jane":80,"Lora":60,"James":75,"Peter":70,"Tom":30,"Ralph":99,"David":55}