dbt — analytics engineering
এই পাঠে যা শিখবেন
- "Analytics engineer" role — dbt কেন এটি জন্ম দিল
- Model, ref, source — তিন core concept
- Materialization choice — কোনটি কখন
- Tests, snapshots, documentation — production-grade analytics
১ · Analytics engineer — নতুন একটি role
২০২০-র আগে dataworld-এ দু'টি প্রধান role: data engineer (pipeline বানায়, Python/Spark) ও data analyst (BI dashboard, SQL)। মাঝে একটি gap — কে warehouse-এ SQL transformation বানাবে?
dbtdbt (data Build Tool)২০১৬-তে Fishtown Analytics (এখন dbt Labs)-এ Tristan Handy তৈরি। Open-source dbt Core + paid dbt Cloud। আজকের modern data stack-এর কেন্দ্রীয় উপাদান। এই gap পূরণ করেছে — এবং একটি নতুন role জন্ম দিয়েছে: analytics engineer। SQL জানে, software engineering practice (Git, test, CI/CD) জানে, business context বোঝে।
১) SELECT-only: কোনো INSERT/UPDATE/DELETE নয়। dbt-ই DDL handle করে।
২) Modular: ছোট ছোট model — একটিতে এক transformation।
৩) Testable: প্রতিটি model-এ assertion (unique, not-null, relationship)।
৪) Documented: YAML-এ description; auto-generated docs site।
২ · একটি dbt model দেখা যাক
Daraz-এর order data থেকে customer summary বানাচ্ছি — তিন stage-এ:
{{ config(materialized='view') }}
-- Source থেকে clean staging layer
select
order_id,
customer_id,
cast(order_date as date) as order_date,
cast(amount as numeric(18, 2)) as amount_bdt,
lower(trim(status)) as status
from {{ source('raw', 'orders') }}
where order_date is not null
SELECT। dbt run করলে warehouse-এ stg_orders নামে view তৈরি। {{ source('raw', 'orders') }} = Jinja templating, dbt resolve করে actual table name-এ।
৩ · ref() — dbt-এর সবচেয়ে গুরুত্বপূর্ণ function
একটি model অন্য model-এ depend করে। কিন্তু hard-code table name লেখা ভঙ্গুর — dev/prod-এ আলাদা schema, naming convention বদলায়।
{{ ref('model_name') }} — এই magic function দু'টি কাজ করে:
- Model name → actual fully-qualified table name resolve।
- Dependency graph (DAG) auto-build। dbt জানে কোনটা আগে run।
{{ config(materialized='table') }}
-- প্রতিটি customer-এর LTV summary
with orders as (
select * from {{ ref('stg_orders') }}
where status = 'completed'
)
select
customer_id,
count(*) as order_count,
sum(amount_bdt) as lifetime_value_bdt,
avg(amount_bdt) as avg_order_value,
min(order_date) as first_order,
max(order_date) as last_order,
current_date - max(order_date) as days_since_last_order
from orders
group by customer_id
{{ ref('stg_orders') }} দেখে dbt বুঝবে — customer_summary stg_orders-এর উপর depend। তাই dbt run করলে — আগে stg_orders, পরে customer_summary।
৪ · Materialization — চারটি option
একই SELECT কিন্তু dbt warehouse-এ চার ভিন্ন রকম materialize করতে পারে:
-
view: warehouse-এ
CREATE VIEW। Storage cost নেই, কিন্তু query-time-এ run। ছোট, frequently changing data-তে। -
table:
CREATE TABLE AS SELECT। প্রতি dbt run-এ পুরো rebuild। Read fast, কিন্তু rebuild expensive। - incremental: প্রথমবার full table; পরে শুধু new/changed row append। বড় fact table-এর জন্য আদর্শ।
- ephemeral: CTE হিসেবে inline। কোনো object তৈরি হয় না। Helper কাজে।
Incremental example:
{{ config(
materialized='incremental',
unique_key='transaction_id',
on_schema_change='append_new_columns'
) }}
select
transaction_id,
user_id,
amount,
transaction_at,
-- bKash style: derived columns
case when amount > 50000 then 'high' else 'normal' end as size_bucket
from {{ ref('stg_transactions') }}
{% if is_incremental() %}
-- শুধু last run-এর পর-এর data
where transaction_at >= (
select coalesce(max(transaction_at), '1900-01-01')
from {{ this }}
)
{% endif %}
{% if is_incremental() %} — Jinja template। প্রথমবার run-এ table-টা যেহেতু নেই, এই block skip; full data load। পরের run-এ শুধু new transaction। unique_key দিয়ে duplicate handle।
where transaction_at >= max - interval '3 days'। বা full_refresh মাঝে মাঝে।
৫ · Tests — data quality assertion
dbt-এর সবচেয়ে loved feature — built-in test। YAML-এ একটা লাইন লিখলে — প্রতিটি run-এ assertion check।
version: 2
models:
- name: customer_summary
description: "Daraz customer LTV — refreshed daily"
columns:
- name: customer_id
description: "Unique customer identifier"
tests:
- unique
- not_null
- name: order_count
tests:
- not_null
- dbt_utils.accepted_range:
min_value: 1
- name: lifetime_value_bdt
tests:
- not_null
- name: fct_transactions
columns:
- name: transaction_id
tests:
- unique
- not_null
- name: user_id
tests:
- not_null
- relationships:
to: ref('dim_users')
field: user_id
unique, not_null, accepted_values, relationships. dbt test command এ সব test চলে; fail হলে exit code non-zero — CI/CD ভাঙে। dbt_utils package-এ আরও ১০০+ test।
৬ · Sources — raw layer-এর declaration
dbt-এ raw data (ELT-এর "EL" থেকে আসা) "source" হিসেবে declare করতে হয়। YAML-এ:
version: 2
sources:
- name: raw
description: "Raw data ingested from operational systems"
schema: raw_daraz
tables:
- name: orders
description: "Order events from MySQL — ingested by Fivetran"
loaded_at_field: _fivetran_synced
freshness:
warn_after: {count: 12, period: hour}
error_after: {count: 24, period: hour}
columns:
- name: order_id
tests:
- unique
- not_null
- name: customers
loaded_at_field: updated_at
dbt source freshness — raw table-এ recent load-এর check। ১২ ঘণ্টা না update হলে warning, ২৪ ঘণ্টায় error। Pipeline upstream broken indicator।
৭ · Snapshot — slowly changing dimension
Daraz-এ আজ একটি customer-এর address "Dhaka", আগামীকাল "Chattogram"। Old order Dhaka-এ মেপে দেখাবেন না Chattogram-এ? — এটি classic SCD (Slowly Changing Dimension) সমস্যা।
Snapshotdbt SnapshotSCD type-2 implementation। প্রতিটি change-এ valid_from / valid_to দিয়ে history track। dbt automatic detect ও handle করে। = SCD type-2-এর dbt implementation। প্রতি change-এ history-তে নতুন row যোগ; পুরাতন row-এ valid_to set।
{% snapshot customers_snapshot %}
{{ config(
target_schema='snapshots',
unique_key='customer_id',
strategy='timestamp',
updated_at='updated_at'
) }}
select * from {{ source('raw', 'customers') }}
{% endsnapshot %}
dbt snapshot চালালে — প্রতি new updated_at-এ history row যোগ। Reporting-এ historical join সম্ভব।
৮ · dbt Core বনাম dbt Cloud
-
dbt Core (free, open-source):
- CLI tool:
dbt run,dbt test,dbt docs serve। - আপনি hosting (Airflow, GitHub Actions) ব্যবস্থা।
- সব feature available।
- Bangladesh-এ ছোট team, cost-conscious — এটাই বেছে নেয়।
- CLI tool:
-
dbt Cloud (paid SaaS, $100+/dev/month):
- Browser-based IDE।
- Managed scheduler — Airflow আলাদাভাবে দরকার নেই।
- CI/CD built-in (PR check, slim CI)।
- Hosted docs site, lineage UI।
- Bangladesh-এ বড় enterprise (BRAC bank, Robi)-এ আসছে।
৯ · একটি dbt project কেমন দেখায়
daraz_dwh/
├── dbt_project.yml # project-level config
├── profiles.yml # warehouse credentials (gitignored)
├── packages.yml # dbt-utils, dbt-expectations
├── models/
│ ├── staging/
│ │ ├── _sources.yml
│ │ ├── stg_orders.sql
│ │ ├── stg_customers.sql
│ │ └── stg_products.sql
│ ├── intermediate/
│ │ └── int_orders_with_customer.sql
│ └── marts/
│ ├── _marts.yml # tests, docs
│ ├── fct_orders.sql
│ ├── dim_customers.sql
│ └── customer_summary.sql
├── snapshots/
│ └── customers_snapshot.sql
├── tests/ # custom SQL tests
│ └── assert_revenue_positive.sql
├── seeds/ # static CSV → table
│ └── country_codes.csv
└── macros/ # reusable Jinja
└── generate_schema_name.sql
# Run commands:
dbt deps # install packages
dbt run # build all models
dbt test # run all tests
dbt docs generate # build docs
dbt docs serve # local docs site at :8080
dbt run dependency order-এ models build। Failed model-এর downstream skip। ১,০০০+ model-ও dbt smooth সামলায়।
~/.dbt/profiles.yml-এ রাখুন বা environment variable: password: "{{ env_var('DBT_PASSWORD') }}"।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১ "ELT" নাকি "ETL" — dbt কোনটিকে enable করে এবং কেন? Bangladesh-এর context-এ এই shift practical কতটুকু?
dbt স্পষ্টভাবেই ELT-এর tool। বুঝতে হলে আগে তিনটি step-এর order বুঝে নিন।
ETL (পুরাতন paradigm, ১৯৯০-২০১০):
- Extract: source থেকে data বের করুন।
- Transform: আলাদা compute server (Informatica, Talend)-এ transform।
- Load: warehouse-এ load।
- Warehouse expensive ছিল — minimal data রাখা।
ELT (modern, ২০১৫+):
- Extract: source থেকে।
- Load: raw data সরাসরি warehouse-এ।
- Transform: warehouse-এর ভেতরেই SQL দিয়ে।
- Cloud warehouse (Snowflake, BigQuery) cheap ও fast — raw রাখা সম্ভব।
কেন ELT জিতছে:
- Cloud economics: Snowflake/BigQuery storage cents/GB। compute decoupled।
- Schema-on-read: raw রাখলে — পরে নতুন transformation possible original থেকে।
- SQL ubiquity: আরও বেশি লোক SQL জানে — Python/Spark কম।
- Vendor offload: Fivetran, Airbyte EL handle; dbt T।
dbt-এর ভূমিকা:
- "T" layer-এর tool।
- Raw warehouse-এ থাকা মানে — dbt-এর কাজের জায়গা warehouse।
- Spark/EMR-এর জটিল compute layer extra।
Bangladesh-এর reality:
- Cost concern: Snowflake credit-এ ১০ জন অ্যানালিস্টের warehouse — মাসে $২,০০০-৫,০০০। ছোট startup-এর জন্য বেশি।
- Alternative: ClickHouse self-hosted, BigQuery free tier ($৩০০ credit), Postgres warehouse pattern।
- EL tool: Fivetran expensive। Airbyte open-source — popular bd-তে। Custom Python script-ও common।
- Bandwidth: বড় data extract slow connection-এ — incremental EL critical।
- Skill gap: dbt শিখতে শুধু SQL + Git। এটি বড় advantage।
Practical scenarios:
- BRAC Bank reporting: ELT excellent — সব transaction Snowflake/Synapse-এ load, dbt-এ analytics।
- bKash fraud detection: ELT কাজে আসে না — sub-second latency দরকার, streaming ETL।
- Daraz BI dashboard: ELT perfect — overnight refresh যথেষ্ট।
- BTRC compliance reports: ELT — historical data যেমন ছিল accurately preserve।
Hybrid pattern:
- "ETLT" — light transform (PII masking, format) load-এর সময়; deep transform warehouse-এ।
- Operational systems-এ heavy compute না করতে।
মূল কথা: Cloud warehouse + dbt = analytics future। Bangladesh-এর enterprise এই path-এ আসছে। কিন্তু streaming ও ML inference আলাদা stack — ELT সবকিছুর সমাধান নয়।
প্র ০২ "Materialization" choice কঠিন। ১০০ GB transactions table-এ কখন view, কখন table, কখন incremental? ভুল choice-এর consequence কী?
Materialization decision = cost vs latency vs complexity trade-off। প্রতিটি model-এ আলাদা।
View — কখন:
- Source table ছোট (১ GB-র নিচে)।
- Query infrequent (প্রতিদিন ১-১০ বার)।
- Underlying data fresh চাই।
- Storage cost-sensitive।
View — সমস্যা ১০০ GB-তে:
- প্রতি query-তে ১০০ GB scan — Snowflake-এ ~$৫।
- BI tool ২০ user × ৫ refresh × $৫ = $৫০০/দিন!
- Slow — query-time-এ aggregation চলে।
Table — কখন:
- Read-heavy (BI dashboard, API)।
- Source ছোট-মাঝারি (১০ GB-র নিচে rebuild affordable)।
- Result-এ heavy aggregation/join — pre-compute।
Table — সমস্যা ১০০ GB-তে:
- প্রতি dbt run-এ ১০০ GB rebuild — ৩০ মিনিট, $৫০।
- প্রতিদিন rebuild = $১,৫০০/মাস শুধু এই model-এ।
- Run window দীর্ঘ — downstream wait।
Incremental — ১০০ GB-তে আদর্শ:
- প্রতি run-এ শুধু গতকালের ~৫০ MB process।
- Run time ৩০ সেকেন্ড, cost cents।
- Read fast (table-এর মতো)।
- Trade-off: complexity বেশি, late-arriving data risk।
Decision tree (১০০ GB transaction table):
- "Query কতবার?" — দিনে ১০+: not view।
- "Source কত বড়?" — ১০ GB-র বেশি: not pure table।
- "New row append-only?" — হ্যাঁ: incremental।
- "Update history?" — হ্যাঁ: snapshot বা full refresh weekly।
Recommended pattern (bKash transactions):
# staging: view (cheap, transparent)
stg_transactions: {{ config(materialized='view') }}
# fact: incremental (huge, append-mostly)
fct_transactions: {{ config(
materialized='incremental',
unique_key='transaction_id',
partition_by={'field': 'date', 'data_type': 'date'},
cluster_by=['user_id']
) }}
# summary: table (small, queried often)
daily_revenue_summary: {{ config(materialized='table') }}
ভুল choice consequences:
- View on huge: warehouse bill explosion। Query timeout। Dashboard load slow।
- Table on huge: long run time, schedule miss। Late refresh = stale dashboards।
- Incremental wrong key: duplicate rows, missing data।
- Table on small read-once: wasted storage, complexity।
Late-arriving data trap:
- Incremental-এ
WHERE date >= max(date)= older arriving row miss। - Solution: lookback window (
max - 3 days) + delete-insert। - Or weekly full_refresh:
dbt run --full-refresh -s fct_transactions।
মূল কথা: Materialization = engineering decision, business decision নয়। Volume measure, query pattern monitor, ব্যয় track — তারপর choose।
প্র ০৩ আপনার dbt project-এ ৫০০ model। Junior engineer একটা model পরিবর্তন করতে চায়। কোনগুলো affected হবে? কী CI/CD safeguard লাগে?
এটি real production scenario। dbt-এর lineage capability এখানে ভাল কাজে।
Affected detection:
# downstream impact
dbt list --select +my_model+
# (+ before = upstream, + after = downstream)
# শুধু changed model + downstream
dbt build --select state:modified+ \
--state ./prod-manifest
# Slim CI (PR-এ শুধু changed পরীক্ষা)
dbt build --select state:modified+ \
--defer --state ./prod-manifest
State comparison:
state:modified— current vs main branch-এ যা ভিন্ন।state:new— main-এ নেই।- "manifest.json" আগের build-এর — compare-এর basis।
CI/CD pipeline (GitHub Actions / GitLab):
name: dbt CI
on: pull_request
jobs:
ci:
steps:
- uses: actions/checkout@v3
- run: dbt deps
- run: dbt seed --target ci
- run: dbt build --select state:modified+ \
--defer --state ./prod-manifest \
--target ci
- run: dbt source freshness
Safeguard layers:
- Layer 1 — Static: SQL linter (sqlfluff), naming convention check।
- Layer 2 — Compile:
dbt parse— Jinja syntax error catch। - Layer 3 — Build: changed model + downstream actually build in CI schema।
- Layer 4 — Test: not_null, unique, custom assertion।
- Layer 5 — Compare: dbt-audit-helper দিয়ে old vs new diff।
- Layer 6 — Approval: senior reviewer approve।
- Layer 7 — Deploy: merge → production run।
Defer pattern:
- CI-তে শুধু changed model build।
- Upstream reference — production manifest থেকে।
- ৫০০ model-এর pretty কম resource।
- 10x+ faster CI।
Documentation enforcement:
- dbt-checkpoint hook: undocumented column reject।
required_docs: true— model description ছাড়া fail।
Test coverage:
- Primary key column-এ unique + not_null mandatory।
- Foreign key column-এ relationships test।
- Business rule (revenue > 0, status in valid list) custom test।
Production deployment:
- Blue-green: parallel schema build, atomic rename।
- Or zero-copy clone (Snowflake):
CREATE TABLE x_new CLONE x। - Rollback plan: previous run-এর schema retain (১ দিন)।
Junior onboarding patterns:
- Sandbox schema প্রতি dev-এর:
dbt_alice,dbt_bob। - Pull-request template — checklist (test added? doc updated? lineage checked?)।
- Pair programming — first ৩-৫ PR senior-এর সাথে।
Bangladesh enterprise context:
- Audit log requirement (BB compliance) — সব schema change tracked।
- Data lineage —
dbt docsgenerated diagram regulator-কে দেখানো। - PII handling — dbt-snowflake-এ row access policy + dbt macro।
মূল কথা: dbt + Git + CI/CD = software engineering rigor for analytics। ৫০০ model managing-এর জন্য এই disciplines essential — না হলে production pipeline বছরের পর বছর fragile।
প্র ০৪ "Macros" dbt-এ Jinja-ভিত্তিক reusable code। কোন situation-এ macro লেখা proper? Bangladesh fintech-এর জন্য একটা useful macro design করুন।
Macro = Jinja template যা compile-time-এ SQL generate করে। C-এর preprocessor-এর মতো।
কখন macro proper:
- DRY principle: একই SQL snippet ৩+ model-এ repeat।
- Database-specific abstraction: Snowflake vs BigQuery syntax difference hide।
- Dynamic generation: runtime input (variable) থেকে SQL।
- Custom test: built-in test যথেষ্ট না।
- Project conventions: schema naming, table aliasing standard।
কখন macro নয়:
- একবার ব্যবহৃত SQL — over-engineering।
- Business logic — model-এ থাকা ভাল (visible)।
- Data-dependent logic — macro static, runtime data নয়।
Bangladesh fintech macro 1: BDT formatting
{% macro format_bdt(amount_col) %}
case
when {{ amount_col }} >= 10000000 then
concat(round({{ amount_col }} / 10000000.0, 2), ' কোটি')
when {{ amount_col }} >= 100000 then
concat(round({{ amount_col }} / 100000.0, 2), ' লাখ')
when {{ amount_col }} >= 1000 then
concat(round({{ amount_col }} / 1000.0, 2), ' হাজার')
else cast({{ amount_col }} as varchar)
end
{% endmacro %}
-- Usage:
select {{ format_bdt('total_revenue') }} as revenue_display
from fct_revenue
Bangladesh fintech macro 2: NID validation
{% macro is_valid_nid(nid_col) %}
-- Bangladesh NID: 10, 13, or 17 digits
({{ nid_col }} ~ '^[0-9]{10}$' or
{{ nid_col }} ~ '^[0-9]{13}$' or
{{ nid_col }} ~ '^[0-9]{17}$')
{% endmacro %}
-- Used in test:
{% test valid_nid(model, column_name) %}
select * from {{ model }}
where not {{ is_valid_nid(column_name) }}
and {{ column_name }} is not null
{% endtest %}
Bangladesh fintech macro 3: PII masking
{% macro mask_phone(phone_col) %}
case
when current_role() in ('analyst', 'admin') then {{ phone_col }}
else concat(left({{ phone_col }}, 5), 'XXXXXX')
end
{% endmacro %}
-- Bangladesh phone: 01XXXXXXXXX (11 digits)
-- Show: 01700XXXXXX
Bangladesh fintech macro 4: Fiscal year
{% macro fiscal_year(date_col) %}
case
when extract(month from {{ date_col }}) >= 7
then concat(extract(year from {{ date_col }}), '-',
extract(year from {{ date_col }}) + 1)
else concat(extract(year from {{ date_col }}) - 1, '-',
extract(year from {{ date_col }}))
end
{% endmacro %}
-- Bangladesh fiscal year: July-June
-- 2026-05 → "2025-2026"
-- 2026-08 → "2026-2027"
Bangladesh fintech macro 5: Mobile operator detection
{% macro mobile_operator(phone_col) %}
case
when {{ phone_col }} like '0170%' or {{ phone_col }} like '0171%' or
{{ phone_col }} like '0172%' or {{ phone_col }} like '0173%' or
{{ phone_col }} like '0174%' or {{ phone_col }} like '0175%' or
{{ phone_col }} like '0176%' or {{ phone_col }} like '0177%' or
{{ phone_col }} like '0178%' or {{ phone_col }} like '0179%' then 'Grameenphone'
when {{ phone_col }} like '0181%' or {{ phone_col }} like '0182%' or
{{ phone_col }} like '0183%' or {{ phone_col }} like '0184%' or
{{ phone_col }} like '0185%' or {{ phone_col }} like '0186%' or
{{ phone_col }} like '0187%' or {{ phone_col }} like '0188%' or
{{ phone_col }} like '0189%' then 'Robi'
when {{ phone_col }} like '019%' then 'Banglalink'
when {{ phone_col }} like '015%' then 'Teletalk'
when {{ phone_col }} like '013%' then 'Grameenphone' -- newer
else 'Unknown'
end
{% endmacro %}
Best practices:
- Macro file
macros/ফোল্ডারে। - Naming: verb-based (format_bdt, is_valid_nid)।
- Document with docstring।
- Test macro itself (yes, possible)।
- Package candidate: reusable macros → dbt package publish।
Public packages worth knowing:
- dbt-utils: generate_series, surrogate_key, pivot — daily use।
- dbt-expectations: Great Expectations port — advanced data tests।
- dbt-codegen: auto-generate model SQL from source schema।
মূল কথা: Macro = power tool — sparingly use। Business logic visible-এ থাকুক, plumbing macro-এ। Bangladesh-এর domain-specific macro অসাধারণ contribution হতে পারে।
অনুশীলন
-
লিখুন: bKash-এর daily transaction summary model — date, total_count, total_amount, unique_user_count।
stg_transactionsref করে।-- models/marts/daily_transaction_summary.sql {{ config(materialized='incremental', unique_key='transaction_date') }} select date(transaction_at) as transaction_date, count(*) as total_count, sum(amount) as total_amount_bdt, count(distinct user_id) as unique_user_count, avg(amount) as avg_amount_bdt from {{ ref('stg_transactions') }} where status = 'success' {% if is_incremental() %} and transaction_at >= (select coalesce(max(transaction_date), '1900-01-01') from {{ this }}) {% endif %} group by 1YAML test:
columns: - name: transaction_date tests: [unique, not_null] - name: total_amount_bdt tests: - dbt_utils.accepted_range: min_value: 0 -
Choose materialization: তিন model-এর জন্য কোনটি?
- (ক)
stg_users— ১০ মিলিয়ন row, ৫ GB, daily refresh। - (খ)
fct_clickstream— ৫০০ মিলিয়ন event/day, append-only। - (গ)
top_10_products— daily small aggregation, dashboard।
- (ক) view বা table — ৫ GB rebuild affordable। Read frequency দেখে decide।
- (খ) incremental — append-only fact, huge volume।
partition_by date। - (গ) table — ছোট, dashboard-এ frequent read, fast pre-compute।
- (ক)
-
Test design: Daraz-এর
fct_orders-এ কী কী test যোগ করবেন?columns: - name: order_id tests: [unique, not_null] - name: customer_id tests: - not_null - relationships: to: ref('dim_customers') field: customer_id - name: order_status tests: - accepted_values: values: ['pending', 'confirmed', 'shipped', 'delivered', 'cancelled'] - name: amount_bdt tests: - not_null - dbt_utils.accepted_range: min_value: 0 max_value: 10000000 # 1 কোটি cap - name: order_date tests: - not_null - dbt_utils.expression_is_true: expression: "<= current_date"Custom SQL test (tests/ folder):
-- tests/assert_no_future_orders.sql select * from {{ ref('fct_orders') }} where order_date > current_date
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পাঠ ১৬ · Streaming vs Batch পরবর্তী পাঠ dbt batch-এর tool — streaming-এর জন্য ভিন্ন paradigm।
- পাঠ ১৪ · DAG লেখা ও schedule আগের পাঠ Airflow + dbt একসাথে চালালে dbt run-কে DAG task হিসেবে।
- পাঠ ২৫ · Data quality testing এই পাঠের সাথে সম্পর্কিত dbt test + Great Expectations — production data quality stack।
- সব AI Courses দেখুন ABCL TECH Python, ML, DL, NLP, CV, GenAI, RL, MLOps — সব AI কোর্স একসাথে।
pip install dbt-postgres বা dbt-bigquery দিয়ে শুরু করুন। অথবা
Google Colab-এ
DuckDB + dbt-duckdb adapter দিয়ে full project local-এ চালানো যায়।