Skip to content

5. Pivot Payments with a Jinja Loop

Difficulty: Medium · Topic: Jinja, vars & packages

Turn {{ ref('stg_payments') }} into one row per order with one column per payment method. The methods are credit_card, coupon, bank_transfer and gift_card.

Return order_id, then credit_card_amount, coupon_amount, bank_transfer_amount, gift_card_amount and total_amount. Only payments with status = 'success' count; a method an order did not use is 0, never null. Every order that has any payment row appears, even if none succeeded.

Write the four method columns with a Jinja {% for %} loop over a list, so adding a method later is a one-word change.

Your model is compiled like dbt does and run in DuckDB against 3 test cases, including hidden edge cases.

Sample inputs

{{ ref('stg_payments') }}

payment_idorder_idmethodstatusamount
1100credit_cardsuccess30
2100couponsuccess5
3101bank_transfersuccess12.5
4101credit_cardfail12.5
5102gift_cardsuccess20

Expected output

order_idcredit_card_amountcoupon_amountbank_transfer_amountgift_card_amounttotal_amount
1003050035
1010012.5012.5
1020002020

Hints

Hint 1{% set payment_methods = ['credit_card', 'coupon', 'bank_transfer', 'gift_card'] %} at the top, then loop over it inside the SELECT.
Hint 2Each column is sum(case when method = '{{ m }}' and status = 'success' then amount else 0 end) as {{ m }}_amount. Without else 0 a missing method sums to null.
Hint 3Watch the commas: {{ ',' if not loop.last }} after each column, or put the loop before total_amount and end every column with a comma.

More dbt problems

All dbt problems