- ์นดํ ๊ณ ๋ฆฌ:
์ง๊ณ ํจ์ (๋ฐ์ ํ ๋ฐ์ดํฐ) , ์๋์ฐ ํจ์ (์ผ๋ฐ) , ๋ฐ์ ํ ๋ฐ ์ ํ ๋ฐ์ดํฐ ํจ์ (๋ฐฐ์ด/์ค๋ธ์ ํธ)
ARRAY_AGGยถ
๋ฐฐ์ด๋ก ํผ๋ฒ๋ ์ ๋ ฅ๊ฐ์ ๋ฐํํฉ๋๋ค. ์ ๋ ฅ์ด ๋น์ด ์์ผ๋ฉด ํจ์๋ ๋น ๋ฐฐ์ด์ ๋ฐํํฉ๋๋ค.
- ๋ณ์นญ:
ARRAYAGG
๊ตฌ๋ฌธยถ
์ง๊ณ ํจ์
ARRAY_AGG( [ DISTINCT ] <expr1> ) [ WITHIN GROUP ( <orderby_clause> ) ]
์๋์ฐ ํจ์
ARRAY_AGG( [ DISTINCT ] <expr1> )
[ WITHIN GROUP ( <orderby_clause> ) ]
OVER ( [ PARTITION BY <expr2> ] [ ORDER BY <expr3> [ { ASC | DESC } ] ] [ <window_frame> ] )
์ธ์ยถ
ํ์:
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) ...;
DISTINCT ๋ฐ WITHIN GROUP์ ๋ํด ์๋ก ๋ค๋ฅธ ์ด์ ์ง์ ํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
SELECT ARRAY_AGG(DISTINCT O_ORDERKEY) WITHIN GROUP (ORDER BY O_ORDERSTATUS) ...;
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);
์ด ์๋ 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 | +------------+
์ด ์๋ 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 | | ] | +--------------------------------------------------------------+
์ด ์๋ 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" | | ] | +-----------------------------------------------------------------------------+
์ด ์์ ์์๋ ๋ ๊ฐ์ ๊ฐ๋ณ 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" | | | ] | +---------------+-------------------------------------------------------------+
๋ค์ ์์ ์์๋ ๋ค๋ฅธ ๋ฐ์ดํฐ ์ธํธ๋ฅผ ์ฌ์ฉํฉ๋๋ค. 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))
);
์ด์ ๋ค์ ์ฟผ๋ฆฌ๋ฅผ ์คํํฉ๋๋ค. ์ฌ๊ธฐ์๋ ์ผ๋ถ ๊ฒฐ๊ณผ ์ธํธ๋ง ํ์๋ฉ๋๋ค.
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;
+------------+---------+
| 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" |
| | ] |
...