์นดํ…Œ๊ณ ๋ฆฌ:

์ง‘๊ณ„ ํ•จ์ˆ˜ (๋ฐ˜์ •ํ˜• ๋ฐ์ดํ„ฐ) , ์œˆ๋„์šฐ ํ•จ์ˆ˜ (์ผ๋ฐ˜) , ๋ฐ˜์ •ํ˜• ๋ฐ ์ •ํ˜• ๋ฐ์ดํ„ฐ ํ•จ์ˆ˜ (๋ฐฐ์—ด/์˜ค๋ธŒ์ ํŠธ)

ARRAY_AGGยถ

๋ฐฐ์—ด๋กœ ํ”ผ๋ฒ—๋œ ์ž…๋ ฅ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ž…๋ ฅ์ด ๋น„์–ด ์žˆ์œผ๋ฉด ํ•จ์ˆ˜๋Š” ๋นˆ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๋ณ„์นญ:

ARRAYAGG

๊ตฌ๋ฌธยถ

์ง‘๊ณ„ ํ•จ์ˆ˜

ARRAY_AGG( [ DISTINCT ] <expr1> ) [ WITHIN GROUP ( <orderby_clause> ) ]
Copy

์œˆ๋„์šฐ ํ•จ์ˆ˜

ARRAY_AGG( [ DISTINCT ] <expr1> )
  [ WITHIN GROUP ( <orderby_clause> ) ]
  OVER ( [ PARTITION BY <expr2> ] [ ORDER BY <expr3> [ { ASC | DESC } ] ] [ <window_frame> ] )
Copy

์ธ์žยถ

ํ•„์ˆ˜:

expr1

๋ฐฐ์—ด์— ๋„ฃ์„ ๊ฐ’์„ ๊ฒฐ์ •ํ•˜๋Š” ์‹(์ผ๋ฐ˜์ ์œผ๋กœ ์—ด ์ด๋ฆ„)์ž…๋‹ˆ๋‹ค.

OVER()

OVER ์ ˆ์€ ํ•จ์ˆ˜๊ฐ€ ์œˆ๋„์šฐ ํ•จ์ˆ˜๋กœ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์Œ์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์œˆ๋„์šฐ ํ•จ์ˆ˜ ๊ตฌ๋ฌธ ๋ฐ ์‚ฌ์šฉ๋ฒ• ์„น์…˜์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

์„ ํƒ ์‚ฌํ•ญ:

DISTINCT

๋ฐฐ์—ด์—์„œ ์ค‘๋ณต๋œ ๊ฐ’์„ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.

WITHIN GROUP orderby_clause

๊ฐ ๋ฐฐ์—ด์˜ ๊ฐ’ ์ˆœ์„œ๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ ์‹(์ผ๋ฐ˜์ ์œผ๋กœ ์—ด ์ด๋ฆ„)์„ ํฌํ•จํ•˜๋Š” ์ ˆ์ž…๋‹ˆ๋‹ค.

WITHIN GROUP(ORDER BY) ๊ตฌ๋ฌธ์€ SELECT ๋ฌธ์˜ ๊ธฐ๋ณธ ORDER BY ์ ˆ๊ณผ ๋™์ผํ•œ ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ORDER BY ์„น์…˜์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

PARTITION BY expr2

์‹(์ผ๋ฐ˜์ ์œผ๋กœ ์—ด ์ด๋ฆ„)์„ ์ง€์ •ํ•˜๋Š” ์œˆ๋„์šฐ ํ•จ์ˆ˜ ์ ˆ์ž…๋‹ˆ๋‹ค. ์ด ์‹์€ ํ•จ์ˆ˜๊ฐ€ ์ ์šฉ๋˜๊ธฐ ์ „์— ์ž…๋ ฅ ํ–‰์„ ๊ทธ๋ฃนํ™”ํ•˜๋Š” ํŒŒํ‹ฐ์…˜์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์œˆ๋„์šฐ ํ•จ์ˆ˜ ๊ตฌ๋ฌธ ๋ฐ ์‚ฌ์šฉ๋ฒ• ์„น์…˜์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

ORDER BY expr3 [ { ASC | DESC } ] [ {window_frame} ]

๊ฐ ํŒŒํ‹ฐ์…˜ ๋‚ด์—์„œ ์ฃผ๋ฌธํ•  ์‹๊ณผ ์„ ํƒ์  ์œˆ๋„์šฐ ํ”„๋ ˆ์ž„์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ window_frame ๊ตฌ๋ฌธ์€ ์œˆ๋„์šฐ ํ•จ์ˆ˜ ๊ตฌ๋ฌธ ๋ฐ ์‚ฌ์šฉ๋ฒ• ์„น์…˜์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

์ด ํ•จ์ˆ˜๋ฅผ ๋ฒ”์œ„ ๊ธฐ๋ฐ˜ ํ”„๋ ˆ์ž„๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ORDER BY ์ ˆ์€ ๋‹จ์ผ ์—ด๋งŒ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ํ–‰ ๊ธฐ๋ฐ˜ ํ”„๋ ˆ์ž„์—๋Š” ์ด๋Ÿฌํ•œ ์ œํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค.

LIMIT ๊ฐ€ ์ง€์›๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ฐ˜ํ™˜ยถ

ARRAY ํ˜•์‹์˜ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

ARRAY_AGG๊ฐ€ ๋‹จ์ผ ํ˜ธ์ถœ์— ๋Œ€ํ•ด ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ๋ฐ์ดํ„ฐ ์–‘์€ 16MB์ž…๋‹ˆ๋‹ค.

์‚ฌ์šฉ๋ฒ• ๋…ธํŠธยถ

  • WITHIN GROUP(ORDER BY)์„ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๊ฐ ๋ฐฐ์—ด ๋‚ด์˜ ์š”์†Œ ์ˆœ์„œ๋ฅผ ์˜ˆ์ธกํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. (WITHIN GROUP ์ ˆ ์™ธ๋ถ€์˜ ORDER BY ์ ˆ์€ ํ–‰ ๋‚ด ๋ฐฐ์—ด ์š”์†Œ์˜ ์ˆœ์„œ๊ฐ€ ์•„๋‹ˆ๋ผ ์ถœ๋ ฅ ํ–‰์˜ ์ˆœ์„œ์— ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.)

  • WITHIN GROUP(ORDER BY)์˜ ์‹์— ์ˆซ์ž๋ฅผ ์ง€์ •ํ•˜๋ฉด ์ด ์ˆซ์ž๋Š” SELECT ๋ชฉ๋ก์— ์žˆ๋Š” ์—ด์˜ ์„œ์ˆ˜ ์œ„์น˜๊ฐ€ ์•„๋‹Œ ์ˆซ์ž ์ƒ์ˆ˜๋กœ ๊ตฌ๋ฌธ ๋ถ„์„๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ˆซ์ž๋ฅผ WITHIN GROUP(ORDER BY) ์‹์œผ๋กœ ์ง€์ •ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

  • DISTINCT ๋ฐ WITHIN GROUP์„ ์ง€์ •ํ•˜๋Š” ๊ฒฝ์šฐ, ๋‘˜ ๋‹ค ๋™์ผํ•œ ์—ด์„ ์ฐธ์กฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ:

    SELECT ARRAY_AGG(DISTINCT O_ORDERKEY) WITHIN GROUP (ORDER BY O_ORDERKEY) ...;
    
    Copy

    DISTINCT ๋ฐ WITHIN GROUP์— ๋Œ€ํ•ด ์„œ๋กœ ๋‹ค๋ฅธ ์—ด์„ ์ง€์ •ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

    SELECT ARRAY_AGG(DISTINCT O_ORDERKEY) WITHIN GROUP (ORDER BY O_ORDERSTATUS) ...;
    
    Copy
    SQL compilation error: [ORDERS.O_ORDERSTATUS] is not a valid order by expression
    

    DISTINCT ๋ฐ WITHIN GROUP์— ๋Œ€ํ•ด ๋™์ผํ•œ ์—ด์„ ์ง€์ •ํ•˜๊ฑฐ๋‚˜ DISTINCT๋ฅผ ์ƒ๋žตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • DISTINCT ๋ฐ WITHIN GROUP ์€ OVER ์ ˆ ๋‚ด์— ORDERBY ์ ˆ์ด ์—†๋Š” ๊ฒฝ์šฐ์—๋งŒ ์œˆ๋„์šฐ ํ•จ์ˆ˜ ํ˜ธ์ถœ์— ์ง€์›๋ฉ๋‹ˆ๋‹ค. OVER ์ ˆ์— ORDER BY ์ ˆ์„ ์‚ฌ์šฉํ•˜๋ฉด ์ถœ๋ ฅ ๋ฐฐ์—ด์˜ ๊ฐ’์€ ๋™์ผํ•œ ๊ธฐ๋ณธ ์ˆœ์„œ(์ฆ‰, WITHIN GROUP (ORDER BY expr3) ๊ณผ ๋™์ผํ•œ ์ˆœ์„œ)๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.

  • NULL ๊ฐ’์€ ์ถœ๋ ฅ์—์„œ ์ƒ๋žต๋ฉ๋‹ˆ๋‹ค.

์˜ˆยถ

์•„๋ž˜์˜ ์˜ˆ์‹œ ์ฟผ๋ฆฌ๋Š” ์•„๋ž˜์— ํ‘œ์‹œ๋œ ํ…Œ์ด๋ธ”๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

CREATE TABLE orders (
    o_orderkey INTEGER,         -- unique ID for each order.
    o_clerk VARCHAR,            -- identifies which clerk is responsible.
    o_totalprice NUMBER(12, 2), -- total price.
    o_orderstatus CHAR(1)       -- 'F' = Fulfilled (sent); 
                                -- 'O' = 'Ordered but not yet Fulfilled'.
    );

INSERT INTO orders (o_orderkey, o_orderstatus, o_clerk, o_totalprice) 
  VALUES 
    ( 32123, 'O', 'Clerk#000000321',     321.23),
    ( 41445, 'F', 'Clerk#000000386', 1041445.00),
    ( 55937, 'O', 'Clerk#000000114', 1055937.00),
    ( 67781, 'F', 'Clerk#000000521', 1067781.00),
    ( 80550, 'O', 'Clerk#000000411', 1080550.00),
    ( 95808, 'F', 'Clerk#000000136', 1095808.00),
    (101700, 'O', 'Clerk#000000220', 1101700.00),
    (103136, 'F', 'Clerk#000000508', 1103136.00);
Copy

์ด ์˜ˆ๋Š” ARRAY_AGG()๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์ฟผ๋ฆฌ์˜ ํ”ผ๋ฒ—๋˜์ง€ ์•Š์€ ์ถœ๋ ฅ์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ์ด ์˜ˆ์™€ ๋‹ค์Œ ์˜ˆ ์‚ฌ์ด์˜ ์ถœ๋ ฅ ๋Œ€์กฐ๋Š” ARRAY_AGG()๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ํ”ผ๋ฒ—ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

SELECT O_ORDERKEY AS order_keys
  FROM orders
  WHERE O_TOTALPRICE > 450000
  ORDER BY O_ORDERKEY;
+------------+
| ORDER_KEYS |
|------------|
|      41445 |
|      55937 |
|      67781 |
|      80550 |
|      95808 |
|     101700 |
|     103136 |
+------------+
Copy

์ด ์˜ˆ๋Š” ARRAY_AGG()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ถœ๋ ฅ ์—ด์„ ๋‹จ์ผ ํ–‰์˜ ๋ฐฐ์—ด๋กœ ํ”ผ๋ฒ—ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

SELECT ARRAY_AGG(O_ORDERKEY) WITHIN GROUP (ORDER BY O_ORDERKEY ASC)
  FROM orders 
  WHERE O_TOTALPRICE > 450000;
+--------------------------------------------------------------+
| ARRAY_AGG(O_ORDERKEY) WITHIN GROUP (ORDER BY O_ORDERKEY ASC) |
|--------------------------------------------------------------|
| [                                                            |
|   41445,                                                     |
|   55937,                                                     |
|   67781,                                                     |
|   80550,                                                     |
|   95808,                                                     |
|   101700,                                                    |
|   103136                                                     |
| ]                                                            |
+--------------------------------------------------------------+
Copy

์ด ์˜ˆ๋Š” ARRAY_AGG()์™€ ํ•จ๊ป˜ DISTINCT ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

SELECT ARRAY_AGG(DISTINCT O_ORDERSTATUS) WITHIN GROUP (ORDER BY O_ORDERSTATUS ASC)
  FROM orders 
  WHERE O_TOTALPRICE > 450000
  ORDER BY O_ORDERSTATUS ASC;
+-----------------------------------------------------------------------------+
| ARRAY_AGG(DISTINCT O_ORDERSTATUS) WITHIN GROUP (ORDER BY O_ORDERSTATUS ASC) |
|-----------------------------------------------------------------------------|
| [                                                                           |
|   "F",                                                                      |
|   "O"                                                                       |
| ]                                                                           |
+-----------------------------------------------------------------------------+
Copy

์ด ์˜ˆ์ œ์—์„œ๋Š” ๋‘ ๊ฐœ์˜ ๊ฐœ๋ณ„ ORDER BY ์ ˆ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ•˜๋‚˜๋Š” ๊ฐ ํ–‰ ๋‚ด๋ถ€์˜ ์ถœ๋ ฅ ๋ฐฐ์—ด ๋‚ด ์ˆœ์„œ๋ฅผ ์ œ์–ดํ•˜๊ณ  ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ์ถœ๋ ฅ ํ–‰์˜ ์ˆœ์„œ๋ฅผ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.

SELECT 
    O_ORDERSTATUS, 
    ARRAYAGG(O_CLERK) WITHIN GROUP (ORDER BY O_TOTALPRICE DESC)
  FROM orders 
  WHERE O_TOTALPRICE > 450000
  GROUP BY O_ORDERSTATUS
  ORDER BY O_ORDERSTATUS DESC;
+---------------+-------------------------------------------------------------+
| O_ORDERSTATUS | ARRAYAGG(O_CLERK) WITHIN GROUP (ORDER BY O_TOTALPRICE DESC) |
|---------------+-------------------------------------------------------------|
| O             | [                                                           |
|               |   "Clerk#000000220",                                        |
|               |   "Clerk#000000411",                                        |
|               |   "Clerk#000000114"                                         |
|               | ]                                                           |
| F             | [                                                           |
|               |   "Clerk#000000508",                                        |
|               |   "Clerk#000000136",                                        |
|               |   "Clerk#000000521",                                        |
|               |   "Clerk#000000386"                                         |
|               | ]                                                           |
+---------------+-------------------------------------------------------------+
Copy

๋‹ค์Œ ์˜ˆ์ œ์—์„œ๋Š” ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ ์„ธํŠธ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ARRAY_AGG ํ•จ์ˆ˜๋Š” ROWS BETWEEN ์œˆ๋„์šฐ ํ”„๋ ˆ์ž„์ด ์žˆ๋Š” ์œˆ๋„์šฐ ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ๋จผ์ € ํ…Œ์ด๋ธ”์„ ๋งŒ๋“ค๊ณ  14๊ฐœ์˜ ํ–‰์œผ๋กœ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.

CREATE OR REPLACE TABLE array_data AS (
WITH data AS (
  SELECT 1 a, [1,3,2,4,7,8,10] b
  UNION ALL
  SELECT 2, [1,3,2,4,7,8,10]
  )
SELECT 'Ord'||a o_orderkey, 'c'||value o_clerk, index
  FROM data, TABLE(FLATTEN(b))
);
Copy

์ด์ œ ๋‹ค์Œ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” ์ผ๋ถ€ ๊ฒฐ๊ณผ ์„ธํŠธ๋งŒ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

SELECT o_orderkey,
    ARRAY_AGG(o_clerk) OVER(PARTITION BY o_orderkey ORDER BY o_orderkey
      ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) AS result
  FROM array_data;
Copy
+------------+---------+
| O_ORDERKEY | RESULT  |
|------------+---------|
| Ord1       | [       |
|            |   "c1"  |
|            | ]       |
| Ord1       | [       |
|            |   "c1", |
|            |   "c3"  |
|            | ]       |
| Ord1       | [       |
|            |   "c1", |
|            |   "c3", |
|            |   "c2"  |
|            | ]       |
| Ord1       | [       |
|            |   "c1", |
|            |   "c3", |
|            |   "c2", |
|            |   "c4"  |
|            | ]       |
| Ord1       | [       |
|            |   "c3", |
|            |   "c2", |
|            |   "c4", |
|            |   "c7"  |
|            | ]       |
| Ord1       | [       |
|            |   "c2", |
|            |   "c4", |
|            |   "c7", |
|            |   "c8"  |
|            | ]       |
| Ord1       | [       |
|            |   "c4", |
|            |   "c7", |
|            |   "c8", |
|            |   "c10" |
|            | ]       |
| Ord2       | [       |
|            |   "c1"  |
|            | ]       |
| Ord2       | [       |
|            |   "c1", |
|            |   "c3"  |
|            | ]       |
...