Search

5 Useful Loop Patterns in dbt

5 Useful Loop Patterns in dbt

dbt์—์„œ Jinja ๋ฃจํ”„์˜ 5๊ฐ€์ง€ ์ฃผ์š” ํŒจํ„ด
1.
๋™์  CASE ๋ฌธ ์ƒ์„ฑ
โ€ข
๋ชฉ์ : ์ œํ’ˆ๋ช…๊ณผ ์นดํ…Œ๊ณ ๋ฆฌ ๊ฐ„์˜ ๋งคํ•‘์„ ์ž๋™ํ™”ํ•˜์—ฌ ๋ฐ์ดํ„ฐ ๋ถ„๋ฅ˜๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ˆ˜ํ–‰
โ€ข
๊ตฌํ˜„ ๋ฐฉ๋ฒ•:
{% set type_mapping = { "shirt": "clothing", "truck": "vehicle", "hat": "clothing" } %} case {% for key, value in type_mapping.items() %} when product_name == '{{ key }}' then '{{ value }}' {% endfor %} else 'other' end as product_type
SQL
๋ณต์‚ฌ
โ€ข
์žฅ์ :
โ—ฆ
๋งคํ•‘ ๊ทœ์น™ ๋ณ€๊ฒฝ ์‹œ dictionary๋งŒ ์ˆ˜์ •ํ•˜๋ฉด ๋จ
โ—ฆ
์ˆ˜๋™์œผ๋กœ CASE ๋ฌธ์„ ์ž‘์„ฑํ•  ํ•„์š”๊ฐ€ ์—†์Œ
โ—ฆ
์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ ํ–ฅ์ƒ
2.
UNION ๋ฌธ ์ƒ์„ฑ
โ€ข
๋ชฉ์ : ์—ฌ๋Ÿฌ ๊ด€๋ จ ํ…Œ์ด๋ธ”์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ•˜๋‚˜๋กœ ํ†ตํ•ฉ
โ€ข
๊ตฌํ˜„ ๋ฐฉ๋ฒ•:
{% set products = ["pants", "shirts", "shoes"] %} {% for product in products %} select id, product_name, product_price from {{ ref('seed_' + product) }} {% if not loop.last %}union all{% endif %} {% endfor %}
SQL
๋ณต์‚ฌ
โ€ข
์žฅ์ :
โ—ฆ
์ƒˆ๋กœ์šด ์ œํ’ˆ ํ…Œ์ด๋ธ” ์ถ”๊ฐ€ ์‹œ ๋ฆฌ์ŠคํŠธ๋งŒ ์—…๋ฐ์ดํŠธํ•˜๋ฉด ๋จ
โ—ฆ
๋™์ผํ•œ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง„ ์—ฌ๋Ÿฌ ํ…Œ์ด๋ธ”์„ ์‰ฝ๊ฒŒ ํ†ตํ•ฉ
โ—ฆ
์ฝ”๋“œ ์ค‘๋ณต ์ตœ์†Œํ™”
3.
CTE ์ž๋™ํ™”
โ€ข
๋ชฉ์ : ์—ฌ๋Ÿฌ ์†Œ์Šค ํ…Œ์ด๋ธ”์— ๋Œ€ํ•œ ๊ณตํ†ต ํ…Œ์ด๋ธ” ํ‘œํ˜„์‹์„ ์ž๋™ ์ƒ์„ฑ
โ€ข
๊ตฌํ˜„ ๋ฐฉ๋ฒ•:
{% set sources = ["customers", "orders", "inventories"] %} with {% for source in sources %} {{ source }}_cte as ( select * from {{ ref('seed_' + source) }} ) {% if not loop.last %},{% endif %} {% endfor %}
SQL
๋ณต์‚ฌ
โ€ข
์žฅ์ :
โ—ฆ
๋ณต์žกํ•œ ์กฐ์ธ ์ฟผ๋ฆฌ๋ฅผ ๋” ๊น”๋”ํ•˜๊ฒŒ ๊ตฌ์„ฑ
โ—ฆ
์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ ์†Œ์Šค ์ถ”๊ฐ€๊ฐ€ ์šฉ์ด
โ—ฆ
์ผ๊ด€๋œ CTE ๋„ค์ด๋ฐ ์ปจ๋ฒค์…˜ ์œ ์ง€
4.
์œ ์—ฐํ•œ ์ง‘๊ณ„ ์ฒ˜๋ฆฌ
โ€ข
๋ชฉ์ : ์—ฌ๋Ÿฌ ์ง€์—ญ์ด๋‚˜ ์นดํ…Œ๊ณ ๋ฆฌ์— ๋Œ€ํ•œ ์ง‘๊ณ„๋ฅผ ์ž๋™ํ™”
โ€ข
๊ตฌํ˜„ ๋ฐฉ๋ฒ•:
{% set regions = ["north", "south", "east", "west"] %} select {% for region in regions %} sum({{ region }}_sales) as total_{{ region }}_sales {% if not loop.last %}, {% endif %} {% endfor %}
SQL
๋ณต์‚ฌ
โ€ข
์žฅ์ :
โ—ฆ
์ƒˆ๋กœ์šด ์ง€์—ญ ์ถ”๊ฐ€ ์‹œ ๋ฆฌ์ŠคํŠธ๋งŒ ์ˆ˜์ •ํ•˜๋ฉด ๋จ
โ—ฆ
์ผ๊ด€๋œ ์ง‘๊ณ„ ๋กœ์ง ์ ์šฉ
โ—ฆ
์‹ค์ˆ˜ ๊ฐ€๋Šฅ์„ฑ ๊ฐ์†Œ
5.
ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ ์ƒ์„ฑ
โ€ข
๋ชฉ์ : ํ†ต๊ณ„ ํ•จ์ˆ˜์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋™์ ์œผ๋กœ ์ƒ์„ฑ
โ€ข
๊ตฌํ˜„ ๋ฐฉ๋ฒ•:
{% set percentiles = range(25, 99, 25) %} select {% for p in percentiles %} percentile_cont({{ p }} / 100) within group (order by price) as price_p{{ p }} {% if not loop.last %}, {% endif %} {% endfor %}
SQL
๋ณต์‚ฌ
โ€ข
์žฅ์ :
โ—ฆ
๋ถ„์œ„์ˆ˜ ๊ณ„์‚ฐ์„ ์ž๋™ํ™”
โ—ฆ
ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์˜ ๋ฒ”์œ„๋ฅผ ์‰ฝ๊ฒŒ ์กฐ์ • ๊ฐ€๋Šฅ
โ—ฆ
์—ฌ๋Ÿฌ ์ง€ํ‘œ์— ๋Œ€ํ•œ ์ผ๊ด€๋œ ํ†ต๊ณ„ ๊ณ„์‚ฐ
๋ชจ๋ฒ” ์‚ฌ๋ก€์™€ ์ฃผ์˜์‚ฌํ•ญ:
1.
๋ฃจํ”„ ์‚ฌ์šฉ ์‹œ ๊ณ ๋ ค์‚ฌํ•ญ:
โ€ข
์ ์ ˆํ•œ ๋“ค์—ฌ์“ฐ๊ธฐ๋กœ ๊ฐ€๋…์„ฑ ์œ ์ง€
โ€ข
loop.last๋ฅผ ํ™œ์šฉํ•œ ๊ตฌ๋ถ„์ž(์‰ผํ‘œ ๋“ฑ) ๊ด€๋ฆฌ
โ€ข
๋ช…ํ™•ํ•œ ๋ณ€์ˆ˜๋ช…๊ณผ ์ฃผ์„ ์‚ฌ์šฉ
2.
์„ฑ๋Šฅ ์ตœ์ ํ™”:
โ€ข
๋„ˆ๋ฌด ํฐ ๋ฆฌ์ŠคํŠธ๋‚˜ ๋ณต์žกํ•œ ๋กœ์ง์€ ํ”ผํ•˜๊ธฐ
โ€ข
์ƒ์„ฑ๋œ SQL์˜ ์‹คํ–‰ ๊ณ„ํš ํ™•์ธ
โ€ข
์ ์ ˆํ•œ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ์ž‘์„ฑ
3.
์œ ์ง€๋ณด์ˆ˜์„ฑ:
โ€ข
๋ฆฌ์ŠคํŠธ๋‚˜ ๋”•์…”๋„ˆ๋ฆฌ๋Š” ๋ณ„๋„ ๋งคํฌ๋กœ๋‚˜ ์„ค์ • ํŒŒ์ผ๋กœ ๊ด€๋ฆฌ
โ€ข
๋ฌธ์„œํ™”๋ฅผ ํ†ตํ•œ ํŒจํ„ด ์‚ฌ์šฉ๋ฒ• ๊ณต์œ 
โ€ข
์ผ๊ด€๋œ ๋„ค์ด๋ฐ ์ปจ๋ฒค์…˜ ์œ ์ง€