Snowflake dbt Airbnb Analytics Skill by ara.so — Data Skills collection. This project demonstrates a complete analytics engineering workflow using Snowflake, dbt, and Streamlit. It loads Inside Airbnb open data into Snowflake, transforms it through a layered dbt architecture (staging → intermediate → marts), validates data quality with tests, and serves insights via a Streamlit dashboard. What This Project Does - Raw data ingestion : Loads CSV/GZIP files from Inside Airbnb into Snowflake internal stages - Layered transformations : Implements staging (clean/cast), intermediate (joins/enrichmen…

, ''), ',', '')::decimal(10,2) as price\n```\n\n### Streamlit Connection Timeout\n\n**Error**: `OperationalError: 250001 (08001): Failed to connect`\n\n**Solution**:\n1. Check `config/local_credentials.json` credentials\n2. Verify Snowflake warehouse is running\n3. Add timeout config:\n\n```python\nconn = snowflake.connector.connect(\n ...,\n login_timeout=30,\n network_timeout=30\n)\n```\n\n### Missing Stage Files\n\n**Error**: `File not found` when running loader script\n\n**Solution**:\n1. Verify raw files exist in `data/raw/`\n2. Check file names match loader script expectations\n3. Ensure files are compressed (`.gz`) where expected\n\n### dbt Model Dependency Errors\n\n**Error**: `Compilation Error: Model 'X' depends on a node named 'Y' which was not found`\n\n**Solution**:\n1. Check `{{ ref('model_name') }}` matches actual model file name\n2. Run `dbt deps --profiles-dir .` to install packages\n3. Verify model exists in `models/` directory\n\n## Environment Variables for Production\n\nUse environment variables instead of local credential files:\n\n**dbt `profiles.yml`**:\n\n```yaml\nairbnb_snowflake:\n target: prod\n outputs:\n prod:\n type: snowflake\n account: \"{{ env_var('SNOWFLAKE_ACCOUNT') }}\"\n user: \"{{ env_var('SNOWFLAKE_USER') }}\"\n password: \"{{ env_var('SNOWFLAKE_PASSWORD') }}\"\n role: \"{{ env_var('SNOWFLAKE_ROLE') }}\"\n database: \"{{ env_var('SNOWFLAKE_DATABASE') }}\"\n warehouse: \"{{ env_var('SNOWFLAKE_WAREHOUSE') }}\"\n schema: ANALYTICS\n threads: 4\n```\n\n**Streamlit connection**:\n\n```python\nimport os\n\nconn = snowflake.connector.connect(\n account=os.getenv('SNOWFLAKE_ACCOUNT'),\n user=os.getenv('SNOWFLAKE_USER'),\n password=os.getenv('SNOWFLAKE_PASSWORD'),\n role=os.getenv('SNOWFLAKE_ROLE'),\n warehouse=os.getenv('SNOWFLAKE_WAREHOUSE'),\n database=os.getenv('SNOWFLAKE_DATABASE'),\n schema='ANALYTICS'\n)\n```\n\n## Project Resources\n\n- **GitHub**: [analyticsdurgesh/Snowflake_DBT_Project](https://github.com/analyticsdurgesh/Snowflake_DBT_Project)\n- **Inside Airbnb**: [insideairbnb.com](https://insideairbnb.com/get-the-data/)\n- **dbt Docs**: [docs.getdbt.com](https://docs.getdbt.com/)\n- **Snowflake Docs**: [docs.snowflake.com](https://docs.snowflake.com/)","attachment_filenames":[],"attachments":[],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Snowflake dbt Airbnb Analytics","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Skill by ","type":"text"},{"text":"ara.so","type":"text","marks":[{"type":"link","attrs":{"href":"https://ara.so","title":null}}]},{"text":" — Data Skills collection.","type":"text"}]}]},{"type":"paragraph","content":[{"text":"This project demonstrates a complete analytics engineering workflow using Snowflake, dbt, and Streamlit. It loads Inside Airbnb open data into Snowflake, transforms it through a layered dbt architecture (staging → intermediate → marts), validates data quality with tests, and serves insights via a Streamlit dashboard.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"What This Project Does","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Raw data ingestion","type":"text","marks":[{"type":"strong"}]},{"text":": Loads CSV/GZIP files from Inside Airbnb into Snowflake internal stages","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Layered transformations","type":"text","marks":[{"type":"strong"}]},{"text":": Implements staging (clean/cast), intermediate (joins/enrichment), and mart (dimensions/facts) layers","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Incremental modeling","type":"text","marks":[{"type":"strong"}]},{"text":": Uses Snowflake merge strategy for fact tables","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Data quality","type":"text","marks":[{"type":"strong"}]},{"text":": Generic and singular dbt tests validate uniqueness, relationships, and business rules","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Analytics dashboard","type":"text","marks":[{"type":"strong"}]},{"text":": Streamlit app queries marts for neighbourhood and listing performance","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Data sources","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"listings.csv.gz","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"calendar.csv.gz","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"reviews.csv.gz","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"neighbourhoods.csv","type":"text","marks":[{"type":"code_inline"}]},{"text":" from ","type":"text"},{"text":"Inside Airbnb","type":"text","marks":[{"type":"link","attrs":{"href":"https://insideairbnb.com/get-the-data/","title":null}}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Installation","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Clone and set up environment\ngit clone https://github.com/analyticsdurgesh/Snowflake_DBT_Project.git\ncd Snowflake_DBT_Project\npython3 -m venv .venv\nsource .venv/bin/activate\npip install -r requirements.txt","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Configuration","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"1. Snowflake Credentials","type":"text"}]},{"type":"paragraph","content":[{"text":"Create local-only credential files (ignored by git):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"cp profiles.yml.example profiles.yml\ncp config/local_credentials.example.json config/local_credentials.json","type":"text"}]},{"type":"paragraph","content":[{"text":"profiles.yml","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" (dbt connection):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"yaml"},"content":[{"text":"airbnb_snowflake:\n target: dev\n outputs:\n dev:\n type: snowflake\n account: YOUR_ACCOUNT\n user: YOUR_USER\n password: \"{{ env_var('SNOWFLAKE_PASSWORD') }}\"\n role: YOUR_ROLE\n database: AIRBNB_DB\n warehouse: COMPUTE_WH\n schema: ANALYTICS\n threads: 4\n client_session_keep_alive: False","type":"text"}]},{"type":"paragraph","content":[{"text":"config/local_credentials.json","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" (Streamlit connection):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"json"},"content":[{"text":"{\n \"account\": \"YOUR_ACCOUNT\",\n \"user\": \"YOUR_USER\",\n \"password\": \"YOUR_PASSWORD\",\n \"role\": \"YOUR_ROLE\",\n \"warehouse\": \"COMPUTE_WH\",\n \"database\": \"AIRBNB_DB\",\n \"schema\": \"ANALYTICS\"\n}","type":"text"}]},{"type":"paragraph","content":[{"text":"Use environment variables in production:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"export SNOWFLAKE_PASSWORD=\"your_password\"","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"2. Download Inside Airbnb Data","type":"text"}]},{"type":"paragraph","content":[{"text":"Place raw files in ","type":"text"},{"text":"data/raw/","type":"text","marks":[{"type":"code_inline"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"text"},"content":[{"text":"data/raw/listings.csv.gz\ndata/raw/calendar.csv.gz\ndata/raw/reviews.csv.gz\ndata/raw/neighbourhoods.csv","type":"text"}]},{"type":"paragraph","content":[{"text":"Recommended dataset: New York City from ","type":"text"},{"text":"Inside Airbnb","type":"text","marks":[{"type":"link","attrs":{"href":"https://insideairbnb.com/get-the-data/","title":null}}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Loading Raw Data","type":"text"}]},{"type":"paragraph","content":[{"text":"The Python loader creates Snowflake objects and stages data:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python scripts/load_inside_airbnb_to_snowflake.py","type":"text"}]},{"type":"paragraph","content":[{"text":"What it does","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Executes ","type":"text"},{"text":"setup/snowflake_setup.sql","type":"text","marks":[{"type":"code_inline"}]},{"text":" to create database, schemas, and stage","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Uploads raw files to ","type":"text"},{"text":"INSIDE_AIRBNB_STAGE","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Creates raw tables with headers from CSV files","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Copies staged data into ","type":"text"},{"text":"RAW","type":"text","marks":[{"type":"code_inline"}]},{"text":" schema tables","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Key loader code patterns","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"import snowflake.connector\nimport json\n\n# Load credentials\nwith open('config/local_credentials.json') as f:\n creds = json.load(f)\n\n# Connect to Snowflake\nconn = snowflake.connector.connect(\n account=creds['account'],\n user=creds['user'],\n password=creds['password'],\n role=creds['role'],\n warehouse=creds['warehouse']\n)\n\n# Upload to stage\nconn.cursor().execute(f\"PUT file://data/raw/listings.csv.gz @INSIDE_AIRBNB_STAGE\")\n\n# Copy into raw table\nconn.cursor().execute(\"\"\"\n COPY INTO RAW.LISTINGS\n FROM @INSIDE_AIRBNB_STAGE/listings.csv.gz\n FILE_FORMAT = (TYPE = 'CSV' SKIP_HEADER = 1 FIELD_OPTIONALLY_ENCLOSED_BY = '\"')\n\"\"\")","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"dbt Model Architecture","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Layer Structure","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Layer","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Path","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Purpose","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Example","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Sources","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"models/staging/sources.yml","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Define raw tables","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"RAW.LISTINGS","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Staging","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"models/staging/stg_*.sql","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Clean, cast, standardize","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"stg_airbnb__listings","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Intermediate","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"models/intermediate/int_*.sql","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Joins, enrichment, business logic","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"int_airbnb__listing_enriched","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Marts","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"models/marts/","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Dimensions, facts, aggregates","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"dim_listings","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"fct_listing_calendar","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Staging Layer Example","type":"text"}]},{"type":"paragraph","content":[{"text":"models/staging/stg_airbnb__listings.sql","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"sql"},"content":[{"text":"with source as (\n select * from {{ source('airbnb_raw', 'listings') }}\n),\n\ncleaned as (\n select\n id::bigint as listing_id,\n name::varchar as listing_name,\n host_id::bigint as host_id,\n host_name::varchar as host_name,\n neighbourhood_cleansed::varchar as neighbourhood,\n room_type::varchar as room_type,\n price::varchar as price_raw,\n minimum_nights::int as minimum_nights,\n number_of_reviews::int as number_of_reviews,\n last_review::date as last_review_date,\n reviews_per_month::float as reviews_per_month,\n availability_365::int as availability_365\n from source\n)\n\nselect * from cleaned","type":"text"}]},{"type":"paragraph","content":[{"text":"Key patterns","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"{{ source() }}","type":"text","marks":[{"type":"code_inline"}]},{"text":" for raw table references","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Cast types explicitly with ","type":"text"},{"text":"::","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Standardize column names (snake_case)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Preserve raw columns when cleaning needed downstream","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Intermediate Layer Example","type":"text"}]},{"type":"paragraph","content":[{"text":"models/intermediate/int_airbnb__calendar_enriched.sql","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"sql"},"content":[{"text":"with calendar as (\n select * from {{ ref('stg_airbnb__calendar') }}\n),\n\nlistings as (\n select * from {{ ref('int_airbnb__listing_enriched') }}\n),\n\nenriched as (\n select\n c.listing_id,\n c.calendar_date,\n c.available,\n c.price,\n c.adjusted_price,\n c.minimum_nights,\n c.maximum_nights,\n l.listing_name,\n l.neighbourhood,\n l.room_type,\n l.host_id,\n l.host_name,\n -- Revenue proxy: price when unavailable\n case\n when c.available = false and c.price > 0\n then c.price\n else 0\n end as estimated_revenue\n from calendar c\n left join listings l\n on c.listing_id = l.listing_id\n)\n\nselect * from enriched","type":"text"}]},{"type":"paragraph","content":[{"text":"Key patterns","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"{{ ref() }}","type":"text","marks":[{"type":"code_inline"}]},{"text":" for model dependencies","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Join staging/intermediate models","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Add calculated business logic (revenue proxy)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Keep intermediate models focused on reusable logic","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Incremental Fact Table Example","type":"text"}]},{"type":"paragraph","content":[{"text":"models/marts/fct_listing_calendar.sql","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"sql"},"content":[{"text":"{{\n config(\n materialized='incremental',\n unique_key=['listing_id', 'calendar_date'],\n merge_update_columns=['available', 'price', 'estimated_revenue']\n )\n}}\n\nwith calendar_enriched as (\n select * from {{ ref('int_airbnb__calendar_enriched') }}\n)\n\nselect\n listing_id,\n calendar_date,\n available,\n price,\n adjusted_price,\n minimum_nights,\n maximum_nights,\n neighbourhood,\n room_type,\n host_id,\n estimated_revenue\nfrom calendar_enriched\n\n{% if is_incremental() %}\n where calendar_date > (select max(calendar_date) from {{ this }})\n{% endif %}","type":"text"}]},{"type":"paragraph","content":[{"text":"Key patterns","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"materialized='incremental'","type":"text","marks":[{"type":"code_inline"}]},{"text":" for large fact tables","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"unique_key","type":"text","marks":[{"type":"code_inline"}]},{"text":" for merge strategy (update existing, insert new)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"merge_update_columns","type":"text","marks":[{"type":"code_inline"}]},{"text":" specifies which columns to update","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"is_incremental()","type":"text","marks":[{"type":"code_inline"}]},{"text":" filters new records only on subsequent runs","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"--full-refresh","type":"text","marks":[{"type":"code_inline"}]},{"text":" flag to rebuild from scratch","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Aggregate Mart Example","type":"text"}]},{"type":"paragraph","content":[{"text":"models/marts/agg_neighbourhood_monthly_performance.sql","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"sql"},"content":[{"text":"with listing_monthly as (\n select * from {{ ref('agg_listing_monthly_performance') }}\n)\n\nselect\n neighbourhood,\n year_month,\n count(distinct listing_id) as total_listings,\n sum(total_days) as total_days,\n sum(available_days) as total_available_days,\n sum(unavailable_days) as total_unavailable_days,\n round(avg(availability_rate), 2) as avg_availability_rate,\n round(sum(estimated_revenue), 2) as total_estimated_revenue,\n round(avg(avg_price), 2) as avg_listing_price\nfrom listing_monthly\ngroup by neighbourhood, year_month\norder by neighbourhood, year_month","type":"text"}]},{"type":"paragraph","content":[{"text":"Key patterns","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Aggregate from lower-level marts","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"round()","type":"text","marks":[{"type":"code_inline"}]},{"text":" for clean reporting metrics","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Group by dimensions for dashboards","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"dbt Commands","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Test connection\ndbt debug --profiles-dir .\n\n# Run all models\ndbt run --profiles-dir .\n\n# Run specific model and downstream dependencies\ndbt run --select dim_listings+ --profiles-dir .\n\n# Run incremental models with full refresh\ndbt run --full-refresh --select fct_listing_calendar+ --profiles-dir .\n\n# Run tests\ndbt test --profiles-dir .\n\n# Test specific model\ndbt test --select stg_airbnb__listings --profiles-dir .\n\n# Generate and serve documentation\ndbt docs generate --profiles-dir .\ndbt docs serve --profiles-dir .","type":"text"}]},{"type":"paragraph","content":[{"text":"Common workflows","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# New data load workflow\npython scripts/load_inside_airbnb_to_snowflake.py\ndbt run --full-refresh --select fct_listing_calendar+ --profiles-dir .\ndbt test --profiles-dir .\n\n# Development workflow (iterative)\ndbt run --select +fct_reviews --profiles-dir . # Run model and upstream deps\ndbt test --select fct_reviews --profiles-dir .","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Data Quality Tests","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Generic Tests in Schema Files","type":"text"}]},{"type":"paragraph","content":[{"text":"models/staging/schema.yml","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"yaml"},"content":[{"text":"version: 2\n\nmodels:\n - name: stg_airbnb__listings\n columns:\n - name: listing_id\n tests:\n - unique\n - not_null\n - name: room_type\n tests:\n - accepted_values:\n values: ['Entire home/apt', 'Private room', 'Shared room', 'Hotel room']\n - name: price\n tests:\n - not_null\n - dbt_utils.expression_is_true:\n expression: \">= 0\"\n\n - name: stg_airbnb__calendar\n columns:\n - name: listing_id\n tests:\n - relationships:\n to: ref('stg_airbnb__listings')\n field: listing_id","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Singular Tests","type":"text"}]},{"type":"paragraph","content":[{"text":"tests/no_duplicate_listing_dates.sql","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"sql"},"content":[{"text":"-- Test for duplicate listing-date combinations in fact table\nselect\n listing_id,\n calendar_date,\n count(*) as record_count\nfrom {{ ref('fct_listing_calendar') }}\ngroup by listing_id, calendar_date\nhaving count(*) > 1","type":"text"}]},{"type":"paragraph","content":[{"text":"Key patterns","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Generic tests in ","type":"text"},{"text":"schema.yml","type":"text","marks":[{"type":"code_inline"}]},{"text":" for standard validations","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Singular tests in ","type":"text"},{"text":"tests/","type":"text","marks":[{"type":"code_inline"}]},{"text":" for custom business rules","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Tests return records that FAIL the condition","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"dbt_utils","type":"text","marks":[{"type":"code_inline"}]},{"text":" package for advanced tests","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Install dbt packages","type":"text","marks":[{"type":"strong"}]},{"text":" (","type":"text"},{"text":"packages.yml","type":"text","marks":[{"type":"code_inline"}]},{"text":"):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"yaml"},"content":[{"text":"packages:\n - package: dbt-labs/dbt_utils\n version: 1.1.1","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"dbt deps --profiles-dir .","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Streamlit Dashboard","type":"text"}]},{"type":"paragraph","content":[{"text":"dashboard/streamlit_app.py","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"import streamlit as st\nimport snowflake.connector\nimport pandas as pd\nimport json\n\n# Load credentials\nwith open('config/local_credentials.json') as f:\n creds = json.load(f)\n\[email protected]_resource\ndef get_connection():\n return snowflake.connector.connect(\n account=creds['account'],\n user=creds['user'],\n password=creds['password'],\n role=creds['role'],\n warehouse=creds['warehouse'],\n database=creds['database'],\n schema=creds['schema']\n )\n\ndef run_query(query):\n conn = get_connection()\n return pd.read_sql(query, conn)\n\nst.title(\"Inside Airbnb Analytics Dashboard\")\n\n# Neighbourhood performance\nst.header(\"Top Neighbourhoods by Estimated Revenue\")\nquery = \"\"\"\n SELECT\n neighbourhood,\n total_estimated_revenue,\n avg_availability_rate,\n total_listings\n FROM agg_neighbourhood_monthly_performance\n WHERE year_month = (SELECT MAX(year_month) FROM agg_neighbourhood_monthly_performance)\n ORDER BY total_estimated_revenue DESC\n LIMIT 10\n\"\"\"\ndf = run_query(query)\nst.dataframe(df)\nst.bar_chart(df.set_index('NEIGHBOURHOOD')['TOTAL_ESTIMATED_REVENUE'])\n\n# Room type pricing\nst.header(\"Average Price by Room Type\")\nquery = \"\"\"\n SELECT\n room_type,\n ROUND(AVG(price), 2) as avg_price\n FROM dim_listings\n WHERE price > 0\n GROUP BY room_type\n ORDER BY avg_price DESC\n\"\"\"\ndf = run_query(query)\nst.bar_chart(df.set_index('ROOM_TYPE')['AVG_PRICE'])","type":"text"}]},{"type":"paragraph","content":[{"text":"Run dashboard","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"streamlit run dashboard/streamlit_app.py","type":"text"}]},{"type":"paragraph","content":[{"text":"Key patterns","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"@st.cache_resource","type":"text","marks":[{"type":"code_inline"}]},{"text":" for connection pooling","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Query marts directly for performance","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Filter to latest snapshot with ","type":"text"},{"text":"MAX(year_month)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Keep credentials in separate JSON file","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Common Patterns","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Adding a New Staging Model","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Define source in ","type":"text"},{"text":"models/staging/sources.yml","type":"text","marks":[{"type":"code_inline"}]},{"text":":","type":"text"}]}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"yaml"},"content":[{"text":"sources:\n - name: airbnb_raw\n database: AIRBNB_DB\n schema: RAW\n tables:\n - name: new_table","type":"text"}]},{"type":"ordered_list","attrs":{"order":2,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Create staging model ","type":"text"},{"text":"models/staging/stg_airbnb__new_table.sql","type":"text","marks":[{"type":"code_inline"}]},{"text":":","type":"text"}]}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"sql"},"content":[{"text":"with source as (\n select * from {{ source('airbnb_raw', 'new_table') }}\n),\n\ncleaned as (\n select\n id::bigint as record_id,\n field::varchar as clean_field\n from source\n)\n\nselect * from cleaned","type":"text"}]},{"type":"ordered_list","attrs":{"order":3,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Add tests in ","type":"text"},{"text":"models/staging/schema.yml","type":"text","marks":[{"type":"code_inline"}]},{"text":":","type":"text"}]}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"yaml"},"content":[{"text":"models:\n - name: stg_airbnb__new_table\n columns:\n - name: record_id\n tests:\n - unique\n - not_null","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Creating a Dimension Table","type":"text"}]},{"type":"paragraph","content":[{"text":"models/marts/dim_hosts.sql","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"sql"},"content":[{"text":"with listings as (\n select * from {{ ref('int_airbnb__listing_enriched') }}\n),\n\nhost_agg as (\n select\n host_id,\n max(host_name) as host_name,\n count(*) as total_listings,\n round(avg(price), 2) as avg_listing_price,\n sum(number_of_reviews) as total_reviews\n from listings\n group by host_id\n)\n\nselect * from host_agg","type":"text"}]},{"type":"paragraph","content":[{"text":"Key patterns","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Aggregate from enriched intermediate layer","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"max()","type":"text","marks":[{"type":"code_inline"}]},{"text":" to select representative values","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Include business metrics (counts, averages)","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Monthly Aggregation Pattern","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"sql"},"content":[{"text":"with daily_facts as (\n select * from {{ ref('fct_listing_calendar') }}\n)\n\nselect\n listing_id,\n to_char(calendar_date, 'YYYY-MM') as year_month,\n count(*) as total_days,\n sum(case when available then 1 else 0 end) as available_days,\n sum(case when not available then 1 else 0 end) as unavailable_days,\n round(avg(case when available then 1.0 else 0.0 end), 2) as availability_rate,\n round(sum(estimated_revenue), 2) as estimated_revenue,\n round(avg(price), 2) as avg_price\nfrom daily_facts\ngroup by listing_id, to_char(calendar_date, 'YYYY-MM')","type":"text"}]},{"type":"paragraph","content":[{"text":"Key patterns","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"to_char(date, 'YYYY-MM')","type":"text","marks":[{"type":"code_inline"}]},{"text":" for month grouping in Snowflake","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Calculate rates with ","type":"text"},{"text":"avg(case when condition then 1.0 else 0.0 end)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Aggregate revenue as sum, prices as average","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Troubleshooting","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"dbt Connection Issues","type":"text"}]},{"type":"paragraph","content":[{"text":"Error","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"Database Error in model [...] (...) 250001 (08001): Failed to connect to DB","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"Solution","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Verify ","type":"text"},{"text":"profiles.yml","type":"text","marks":[{"type":"code_inline"}]},{"text":" has correct Snowflake account identifier","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Test connection: ","type":"text"},{"text":"dbt debug --profiles-dir .","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Check Snowflake credentials and network access","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Ensure warehouse is running","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Incremental Model Not Updating","type":"text"}]},{"type":"paragraph","content":[{"text":"Error","type":"text","marks":[{"type":"strong"}]},{"text":": New data not appearing in incremental fact table","type":"text"}]},{"type":"paragraph","content":[{"text":"Solution","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Force full rebuild\ndbt run --full-refresh --select fct_listing_calendar --profiles-dir .","type":"text"}]},{"type":"paragraph","content":[{"text":"Check ","type":"text"},{"text":"unique_key","type":"text","marks":[{"type":"code_inline"}]},{"text":" matches grain in config:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"sql"},"content":[{"text":"{{\n config(\n unique_key=['listing_id', 'calendar_date'] -- Must match table grain\n )\n}}","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Test Failures on Price Data","type":"text"}]},{"type":"paragraph","content":[{"text":"Error","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"dbt_utils.expression_is_true","type":"text","marks":[{"type":"code_inline"}]},{"text":" fails on price column","type":"text"}]},{"type":"paragraph","content":[{"text":"Solution","type":"text","marks":[{"type":"strong"}]},{"text":": Raw price data may contain non-numeric values or currency symbols.","type":"text"}]},{"type":"paragraph","content":[{"text":"Clean in staging layer:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"sql"},"content":[{"text":"-- Remove $ and commas, cast to numeric\nreplace(replace(price, '

Snowflake dbt Airbnb Analytics Skill by ara.so — Data Skills collection. This project demonstrates a complete analytics engineering workflow using Snowflake, dbt, and Streamlit. It loads Inside Airbnb open data into Snowflake, transforms it through a layered dbt architecture (staging → intermediate → marts), validates data quality with tests, and serves insights via a Streamlit dashboard. What This Project Does - Raw data ingestion : Loads CSV/GZIP files from Inside Airbnb into Snowflake internal stages - Layered transformations : Implements staging (clean/cast), intermediate (joins/enrichmen…

, ''), ',', '')::decimal(10,2) as price","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Streamlit Connection Timeout","type":"text"}]},{"type":"paragraph","content":[{"text":"Error","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"OperationalError: 250001 (08001): Failed to connect","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"Solution","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Check ","type":"text"},{"text":"config/local_credentials.json","type":"text","marks":[{"type":"code_inline"}]},{"text":" credentials","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Verify Snowflake warehouse is running","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Add timeout config:","type":"text"}]}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"conn = snowflake.connector.connect(\n ...,\n login_timeout=30,\n network_timeout=30\n)","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Missing Stage Files","type":"text"}]},{"type":"paragraph","content":[{"text":"Error","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"File not found","type":"text","marks":[{"type":"code_inline"}]},{"text":" when running loader script","type":"text"}]},{"type":"paragraph","content":[{"text":"Solution","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Verify raw files exist in ","type":"text"},{"text":"data/raw/","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Check file names match loader script expectations","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Ensure files are compressed (","type":"text"},{"text":".gz","type":"text","marks":[{"type":"code_inline"}]},{"text":") where expected","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"dbt Model Dependency Errors","type":"text"}]},{"type":"paragraph","content":[{"text":"Error","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"Compilation Error: Model 'X' depends on a node named 'Y' which was not found","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"Solution","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Check ","type":"text"},{"text":"{{ ref('model_name') }}","type":"text","marks":[{"type":"code_inline"}]},{"text":" matches actual model file name","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Run ","type":"text"},{"text":"dbt deps --profiles-dir .","type":"text","marks":[{"type":"code_inline"}]},{"text":" to install packages","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Verify model exists in ","type":"text"},{"text":"models/","type":"text","marks":[{"type":"code_inline"}]},{"text":" directory","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Environment Variables for Production","type":"text"}]},{"type":"paragraph","content":[{"text":"Use environment variables instead of local credential files:","type":"text"}]},{"type":"paragraph","content":[{"text":"dbt ","type":"text","marks":[{"type":"strong"}]},{"text":"profiles.yml","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"yaml"},"content":[{"text":"airbnb_snowflake:\n target: prod\n outputs:\n prod:\n type: snowflake\n account: \"{{ env_var('SNOWFLAKE_ACCOUNT') }}\"\n user: \"{{ env_var('SNOWFLAKE_USER') }}\"\n password: \"{{ env_var('SNOWFLAKE_PASSWORD') }}\"\n role: \"{{ env_var('SNOWFLAKE_ROLE') }}\"\n database: \"{{ env_var('SNOWFLAKE_DATABASE') }}\"\n warehouse: \"{{ env_var('SNOWFLAKE_WAREHOUSE') }}\"\n schema: ANALYTICS\n threads: 4","type":"text"}]},{"type":"paragraph","content":[{"text":"Streamlit connection","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"import os\n\nconn = snowflake.connector.connect(\n account=os.getenv('SNOWFLAKE_ACCOUNT'),\n user=os.getenv('SNOWFLAKE_USER'),\n password=os.getenv('SNOWFLAKE_PASSWORD'),\n role=os.getenv('SNOWFLAKE_ROLE'),\n warehouse=os.getenv('SNOWFLAKE_WAREHOUSE'),\n database=os.getenv('SNOWFLAKE_DATABASE'),\n schema='ANALYTICS'\n)","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Project Resources","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"GitHub","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"analyticsdurgesh/Snowflake_DBT_Project","type":"text","marks":[{"type":"link","attrs":{"href":"https://github.com/analyticsdurgesh/Snowflake_DBT_Project","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Inside Airbnb","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"insideairbnb.com","type":"text","marks":[{"type":"link","attrs":{"href":"https://insideairbnb.com/get-the-data/","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"dbt Docs","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"docs.getdbt.com","type":"text","marks":[{"type":"link","attrs":{"href":"https://docs.getdbt.com/","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Snowflake Docs","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"docs.snowflake.com","type":"text","marks":[{"type":"link","attrs":{"href":"https://docs.snowflake.com/","title":null}}]}]}]}]}]},"metadata":{"date":"2026-11-02","name":"snowflake-dbt-airbnb-analytics","author":"@skillopedia","source":{"stars":5,"repo_name":"data-skills","origin_url":"https://github.com/reason-machines/data-skills/blob/HEAD/skills/snowflake-dbt-airbnb-analytics/SKILL.md","repo_owner":"reason-machines","body_sha256":"2ad4e22c4dc19ad3a13c59540be93d72c8687ffd75ec368a5d54f9bf94c39b1a","cluster_key":"fc8de59e1dfff0a537e6b808cb3e4e57095469475b057874271b6de96df0712b","clean_bundle":{"format":"clean-skill-bundle-v1","source":"reason-machines/data-skills/skills/snowflake-dbt-airbnb-analytics/SKILL.md","text_bytes":0,"source_commit":"25d6ee79eea935ef4be1ee375a5777b2ad259f0a","skills_sh_rank":9391,"attachment_count":0,"text_attachments":0,"attachment_storage":"skill_attachments","binary_attachments":0},"cluster_size":1,"skill_md_path":"skills/snowflake-dbt-airbnb-analytics/SKILL.md","import_metadata":{"date":"2026-11-02","author":"@skillopedia","version":"v1","category":"data-analytics","category_label":"Data"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"data-analytics","triggers":["set up snowflake dbt project with inside airbnb data","create dbt models for airbnb listings and calendar","build incremental fact tables in snowflake with dbt","write dbt tests for data quality validation","configure dbt profiles for snowflake connection","add streamlit dashboard to dbt snowflake project","implement analytics engineering layered architecture","create monthly aggregates from airbnb calendar data"],"import_tag":"skills-sh-top20k-2026-11","description":"Inside Airbnb data warehouse built with Snowflake and dbt, demonstrating modern analytics engineering patterns with staging, intermediate, and mart layers."}},"renderedAt":1793666538638}

Snowflake dbt Airbnb Analytics Skill by ara.so — Data Skills collection. This project demonstrates a complete analytics engineering workflow using Snowflake, dbt, and Streamlit. It loads Inside Airbnb open data into Snowflake, transforms it through a layered dbt architecture (staging → intermediate → marts), validates data quality with tests, and serves insights via a Streamlit dashboard. What This Project Does - Raw data ingestion : Loads CSV/GZIP files from Inside Airbnb into Snowflake internal stages - Layered transformations : Implements staging (clean/cast), intermediate (joins/enrichmen…