offdataai
Travel & Hospitality · data model template

Hospitality / Hotel Analytics data model

Kimball warehouse for hospitality: an accumulating reservation snapshot (booked -> stayed -> checked out), a daily occupancy periodic snapshot for ADR/RevPAR, and transaction-grain folio revenue postings over conformed guest/property/room-type/rate-plan/channel dimensions. Guest PII is classified and masked.

Hotel and resort analytics covering the reservation lifecycle, daily occupancy and RevPAR snapshots, and folio revenue postings over conformed guest, property, room-type, rate-plan, and channel dimensions — a Kimball star schema with SCD2 guest history and regulated guest PII (loyalty number, contact details) masked. It is a Kimball dimensional model: fact tables at a declared grain surrounded by conformed dimensions, ready for BI tools and a semantic layer.

KimballTravel & HospitalityPCI-DSSGDPR
10
tables
114
columns
14
relationships
8
PII columns

Opening the template creates a project with the ERD, platform-native DDL, a dbt project and documentation already generated (recommended platform: Snowflake). Edit it in plain English or on the canvas, then ship it to any supported warehouse.

Subject areas

reservationsoccupancyrevenueconformed_dimensions

Design decisions

  • Accumulating snapshot for reservations

    A reservation has well-defined milestones (booking, arrival, departure, cancellation) and a slowly-evolving status — an accumulating snapshot captures lifecycle lag and conversion.

  • Daily occupancy snapshot separate from reservations

    Occupancy, ADR, and RevPAR are semi-additive daily metrics needed at property/room-type grain independent of individual reservations.

  • Folio revenue as a transaction-grain fact

    Revenue postings arrive continuously across revenue centers (room, F&B, spa); a transaction grain supports flexible revenue analysis and reconciliation against the folio.

  • SCD2 on dim_guest

    Loyalty tier and VIP status change over time; SCD2 preserves the guest attributes that were in effect at each stay.

  • Masking on loyalty number and contact PII

    GDPR requires restricting access to personal identifiers; guest email is hashed and contact fields are partially masked.

Tables in the Hospitality / Hotel Analytics model

Every table with its grain, columns, types and keys. PK marks a primary key, BK a business key and PII a column classified as personal data, which gets a masking strategy by default.

Fact tables (3)

fct_reservation

Grain: one row per reservation (accumulating snapshot booked->stayed->checked_out)

Accumulating snapshot tracking the reservation lifecycle milestones.

ColumnTypeKeys
reservation_keybigintPK
guest_keybigint
property_keybigint
room_type_keybigint
rate_plan_keybigint
channel_keybigint
booking_date_keybigint
arrival_date_keybigint
departure_date_keybigint
cancellation_date_keybigint
confirmation_numbervarchar
reservation_statusvarchar
nights_bookedsmallint
nights_stayedsmallint
adults_countsmallint
children_countsmallint
average_daily_ratedecimal
total_room_revenuedecimal
taxes_amountdecimal
deposit_amountdecimal
lead_time_daysinteger
is_cancelledboolean
is_no_showboolean

fct_occupancy_snapshot

Grain: one row per property per room type per day (periodic snapshot)

Daily occupancy snapshot — semi-additive ratios for RevPAR reporting.

ColumnTypeKeys
date_keybigint
property_keybigint
room_type_keybigint
rooms_availableinteger
rooms_soldinteger
rooms_out_of_orderinteger
guest_countinteger
occupancy_ratedecimal
adrdecimal
rev_pardecimal
room_revenuedecimal

fct_folio_revenue

Grain: one row per folio revenue posting line (transaction)

Transaction-grain folio postings across all revenue centers.

ColumnTypeKeys
folio_line_keybigintPK
date_keybigint
guest_keybigint
property_keybigint
reservation_keybigint
revenue_type_keybigint
folio_numbervarchar
posting_descriptionvarchar
quantityinteger
unit_pricedecimal
gross_amountdecimal
discount_amountdecimal
tax_amountdecimal
net_amountdecimal
is_compboolean

Dimension tables (5)

dim_date

Grain: one row per calendar day

ColumnTypeKeys
date_keybigintPK
full_datedateBK
day_of_weekvarchar
month_numbersmallint
month_namevarchar
quartersmallint
yearsmallint
is_weekendboolean
is_holidayboolean
seasonvarchar

dim_guest

Grain: one row per guest per SCD2 version

SCD type 2

ColumnTypeKeys
guest_keybigintPK
guest_idvarcharBK
first_namevarcharPII
last_namevarcharPII
emailvarcharPII
phonevarcharPII
date_of_birthdatePII
address_line1varcharPII
cityvarchar
statevarchar
postal_codevarcharPII
countryvarchar
nationalityvarchar
loyalty_tiervarchar
loyalty_numbervarcharPII
vip_flagboolean
marketing_opt_inboolean

dim_property

Grain: one row per hotel property

ColumnTypeKeys
property_keybigintPK
property_idvarcharBK
property_namevarchar
brandvarchar
property_typevarchar
star_ratingsmallint
total_roomsinteger
cityvarchar
statevarchar
countryvarchar
regionvarchar
timezonevarchar

dim_room_type

Grain: one row per room type

ColumnTypeKeys
room_type_keybigintPK
room_type_idvarcharBK
room_type_namevarchar
bed_configurationvarchar
max_occupancysmallint
square_feetinteger
view_typevarchar
is_smokingboolean
is_accessibleboolean

dim_rate_plan

Grain: one row per rate plan

ColumnTypeKeys
rate_plan_keybigintPK
rate_plan_idvarcharBK
rate_plan_namevarchar
rate_categoryvarchar
is_refundableboolean
includes_breakfastboolean
min_stay_nightssmallint
advance_purchase_dayssmallint

Lookup tables (2)

dim_channel

Grain: one row per booking channel

ColumnTypeKeys
channel_keybigintPK
channel_codevarcharBK
channel_namevarchar
channel_groupvarchar
commission_ratedecimal

dim_revenue_type

Grain: one row per folio revenue type

ColumnTypeKeys
revenue_type_keybigintPK
revenue_type_codevarcharBK
revenue_type_namevarchar
revenue_categoryvarchar

Relationships

Each relationship is a foreign key on the first table referencing the second.

  • fct_reservation.guest_key → dim_guest (many-to-one)
  • fct_reservation.property_key → dim_property (many-to-one)
  • fct_reservation.room_type_key → dim_room_type (many-to-one)
  • fct_reservation.rate_plan_key → dim_rate_plan (many-to-one)
  • fct_reservation.channel_key → dim_channel (many-to-one)
  • fct_reservation.booking_date_key → dim_date (many-to-one)
  • fct_occupancy_snapshot.date_key → dim_date (many-to-one)
  • fct_occupancy_snapshot.property_key → dim_property (many-to-one)
  • fct_occupancy_snapshot.room_type_key → dim_room_type (many-to-one)
  • fct_folio_revenue.date_key → dim_date (many-to-one)
  • fct_folio_revenue.guest_key → dim_guest (many-to-one)
  • fct_folio_revenue.property_key → dim_property (many-to-one)
  • fct_folio_revenue.reservation_key → fct_reservation (many-to-one)
  • fct_folio_revenue.revenue_type_key → dim_revenue_type (many-to-one)

Related templates

All templates →
Start for $1

From requirements to AI-ready context, in one platform.

Describe your business in a conversation, start from a template or connect your own database. Your first model is ready in minutes.

Get startedBook a demo

Plans from $1/month · cancel any time