| 1 | -- OLAP queries
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 | -- 1) revenues - ROLLUP po hotel, godina, kvartal
|
|---|
| 5 |
|
|---|
| 6 | SELECT
|
|---|
| 7 | COALESCE(h.hotel_name, '──') AS hotel,
|
|---|
| 8 | COALESCE(d.year::TEXT, '──') AS year,
|
|---|
| 9 | COALESCE(d.quarter::TEXT,'──') AS quarter,
|
|---|
| 10 | COUNT(*) AS reservations,
|
|---|
| 11 | SUM(f.total_cost) AS revenue,
|
|---|
| 12 | ROUND(AVG(f.total_cost), 2) AS avg_per_reservation
|
|---|
| 13 | FROM FactReservation f
|
|---|
| 14 | JOIN DimDate d ON d.date_key = f.date_key
|
|---|
| 15 | JOIN DimHotel h ON h.hotel_key = f.hotel_key
|
|---|
| 16 | WHERE f.status != 'cancelled'
|
|---|
| 17 | GROUP BY ROLLUP(h.hotel_name, d.year, d.quarter)
|
|---|
| 18 | ORDER BY h.hotel_name, d.year, d.quarter;
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 | -- 2) occupancy Rate po hotel i sezona - CUBE
|
|---|
| 22 | SELECT
|
|---|
| 23 | COALESCE(h.hotel_name, '──') AS hotel,
|
|---|
| 24 | COALESCE(d.season, '──') AS season,
|
|---|
| 25 | COUNT(*) AS total_reservations,
|
|---|
| 26 | COUNT(*) FILTER (WHERE f.status = 'completed') AS completed,
|
|---|
| 27 | ROUND(
|
|---|
| 28 | COUNT(*) FILTER (WHERE f.status = 'completed') * 100.0
|
|---|
| 29 | / NULLIF(COUNT(*), 0)
|
|---|
| 30 | , 1) AS occupancy_pct,
|
|---|
| 31 | ROUND(AVG(f.nights_stayed), 1) AS avg_nights
|
|---|
| 32 | FROM FactReservation f
|
|---|
| 33 | JOIN DimDate d ON d.date_key = f.date_key
|
|---|
| 34 | JOIN DimHotel h ON h.hotel_key = f.hotel_key
|
|---|
| 35 | GROUP BY CUBE(h.hotel_name, d.season)
|
|---|
| 36 | ORDER BY h.hotel_name, d.season;
|
|---|
| 37 |
|
|---|
| 38 |
|
|---|
| 39 | -- 3) Drill Down - pronaogjanje na pricini za pagjanje na prihodot
|
|---|
| 40 |
|
|---|
| 41 | --1. po godina
|
|---|
| 42 | SELECT
|
|---|
| 43 | d.year,
|
|---|
| 44 | SUM(f.total_cost) AS revenue,
|
|---|
| 45 | LAG(SUM(f.total_cost)) OVER (ORDER BY d.year) AS prev_year,
|
|---|
| 46 | ROUND(
|
|---|
| 47 | (SUM(f.total_cost) - LAG(SUM(f.total_cost)) OVER (ORDER BY d.year))
|
|---|
| 48 | * 100.0
|
|---|
| 49 | / NULLIF(LAG(SUM(f.total_cost)) OVER (ORDER BY d.year), 0)
|
|---|
| 50 | , 1) AS growth_pct -- % промена vs минатата година
|
|---|
| 51 | FROM FactReservation f
|
|---|
| 52 | JOIN DimDate d ON d.date_key = f.date_key
|
|---|
| 53 | WHERE f.status != 'cancelled'
|
|---|
| 54 | GROUP BY d.year
|
|---|
| 55 | ORDER BY d.year;
|
|---|
| 56 |
|
|---|
| 57 | --2. za konkretna godina po hotel
|
|---|
| 58 | SELECT
|
|---|
| 59 | h.hotel_name,
|
|---|
| 60 | SUM(f.total_cost) AS revenue
|
|---|
| 61 | FROM FactReservation f
|
|---|
| 62 | JOIN DimDate d ON d.date_key = f.date_key
|
|---|
| 63 | JOIN DimHotel h ON h.hotel_key = f.hotel_key
|
|---|
| 64 | WHERE d.year = 2022
|
|---|
| 65 | AND f.status != 'cancelled'
|
|---|
| 66 | GROUP BY h.hotel_name
|
|---|
| 67 | ORDER BY revenue;
|
|---|
| 68 |
|
|---|
| 69 | --3. za konkreten hotel po species
|
|---|
| 70 | SELECT
|
|---|
| 71 | s.species_name,
|
|---|
| 72 | COUNT(*) AS reservations,
|
|---|
| 73 | SUM(f.total_cost) AS revenue
|
|---|
| 74 | FROM FactReservation f
|
|---|
| 75 | JOIN DimDate d ON d.date_key = f.date_key
|
|---|
| 76 | JOIN DimHotel h ON h.hotel_key = f.hotel_key
|
|---|
| 77 | JOIN DimPet p ON p.pet_key = f.pet_key
|
|---|
| 78 | JOIN DimSpecies s ON p.species_key = s.species_key
|
|---|
| 79 | WHERE d.year = 2022
|
|---|
| 80 | AND h.hotel_name = 'Fur Haven'
|
|---|
| 81 | AND f.status != 'cancelled'
|
|---|
| 82 | GROUP BY s.species_name
|
|---|
| 83 | ORDER BY revenue;
|
|---|
| 84 |
|
|---|
| 85 | --4. za konkreten species po mesec
|
|---|
| 86 | SELECT
|
|---|
| 87 | d.month_name,
|
|---|
| 88 | d.month_num,
|
|---|
| 89 | COUNT(*) AS reservations,
|
|---|
| 90 | SUM(f.total_cost) AS revenue
|
|---|
| 91 | FROM FactReservation f
|
|---|
| 92 | JOIN DimDate d ON d.date_key = f.date_key
|
|---|
| 93 | JOIN DimHotel h ON h.hotel_key = f.hotel_key
|
|---|
| 94 | JOIN DimPet p ON p.pet_key = f.pet_key
|
|---|
| 95 | JOIN DimSpecies s ON p.species_key = s.species_key
|
|---|
| 96 | WHERE d.year = 2022
|
|---|
| 97 | AND h.hotel_name = 'Fur Haven'
|
|---|
| 98 | AND s.species_name = 'Dog'
|
|---|
| 99 | AND f.status != 'cancelled'
|
|---|
| 100 | GROUP BY d.month_name, d.month_num
|
|---|
| 101 | ORDER BY d.month_num;
|
|---|
| 102 |
|
|---|
| 103 |
|
|---|
| 104 |
|
|---|
| 105 | -- 4) top uslugi po prihod - Window functions
|
|---|
| 106 | SELECT
|
|---|
| 107 | ds.service_name,
|
|---|
| 108 | h.hotel_name,
|
|---|
| 109 | COUNT(*) AS times_used,
|
|---|
| 110 | SUM(f.price) AS total_revenue,
|
|---|
| 111 |
|
|---|
| 112 | RANK() OVER (
|
|---|
| 113 | PARTITION BY h.hotel_name
|
|---|
| 114 | ORDER BY SUM(f.price) DESC
|
|---|
| 115 | ) AS rank_in_hotel,
|
|---|
| 116 |
|
|---|
| 117 | ROUND(
|
|---|
| 118 | SUM(f.price) * 100.0
|
|---|
| 119 | / SUM(SUM(f.price)) OVER (PARTITION BY h.hotel_name)
|
|---|
| 120 | , 1) AS pct_of_hotel_revenue
|
|---|
| 121 | FROM FactServiceUsage f
|
|---|
| 122 | JOIN DimService ds ON ds.service_key = f.service_key
|
|---|
| 123 | JOIN DimHotel h ON h.hotel_key = f.hotel_key
|
|---|
| 124 | WHERE f.status = 'completed'
|
|---|
| 125 | GROUP BY ds.service_name, h.hotel_name
|
|---|
| 126 | ORDER BY h.hotel_name, rank_in_hotel;
|
|---|
| 127 |
|
|---|
| 128 |
|
|---|
| 129 |
|
|---|
| 130 | -- 5) Customer Lifetime Value - najvredni klienti
|
|---|
| 131 | SELECT
|
|---|
| 132 | c.customer_key,
|
|---|
| 133 | c.full_name,
|
|---|
| 134 | c.customer_segment,
|
|---|
| 135 | COUNT(DISTINCT f.reservation_key) AS total_reservations,
|
|---|
| 136 | SUM(f.total_cost) AS lifetime_value,
|
|---|
| 137 | ROUND(AVG(f.total_cost), 2) AS avg_per_visit,
|
|---|
| 138 | MIN(d.full_date) AS first_visit,
|
|---|
| 139 | MAX(d.full_date) AS last_visit,
|
|---|
| 140 | RANK() OVER (
|
|---|
| 141 | ORDER BY SUM(f.total_cost) DESC
|
|---|
| 142 | ) AS overall_rank,
|
|---|
| 143 | RANK() OVER (
|
|---|
| 144 | PARTITION BY c.customer_segment
|
|---|
| 145 | ORDER BY SUM(f.total_cost) DESC
|
|---|
| 146 | ) AS segment_rank
|
|---|
| 147 | FROM FactReservation f
|
|---|
| 148 | JOIN DimCustomer c ON c.customer_key = f.customer_key
|
|---|
| 149 | JOIN DimDate d ON d.date_key = f.date_key
|
|---|
| 150 | WHERE f.status = 'completed'
|
|---|
| 151 | GROUP BY c.customer_key, c.full_name, c.customer_segment
|
|---|
| 152 | ORDER BY lifetime_value DESC
|
|---|
| 153 | LIMIT 20;
|
|---|
| 154 |
|
|---|
| 155 | -- 6) prodazba po kategorija, hotel - CUBE
|
|---|
| 156 | SELECT
|
|---|
| 157 | COALESCE(dp.category_name, '──') AS category,
|
|---|
| 158 | COALESCE(h.hotel_name, '──') AS hotel,
|
|---|
| 159 | COALESCE(dp.price_range, '──') AS price_range,
|
|---|
| 160 | SUM(f.quantity) AS units_sold,
|
|---|
| 161 | SUM(f.total_price) AS revenue,
|
|---|
| 162 | ROUND(AVG(f.unit_price), 2) AS avg_price
|
|---|
| 163 | FROM FactOrderProduct f
|
|---|
| 164 | JOIN DimProduct dp ON dp.product_key = f.product_key
|
|---|
| 165 | JOIN DimHotel h ON h.hotel_key = f.hotel_key
|
|---|
| 166 | WHERE f.order_status = 'completed'
|
|---|
| 167 | GROUP BY CUBE(dp.category_name, h.hotel_name, dp.price_range)
|
|---|
| 168 | ORDER BY dp.category_name, h.hotel_name;
|
|---|
| 169 |
|
|---|
| 170 |
|
|---|
| 171 | -- 7) Pivoting - sporedba na prihodi na sobi vo razlicni hoteli
|
|---|
| 172 |
|
|---|
| 173 | SELECT
|
|---|
| 174 | h.hotel_name,
|
|---|
| 175 | SUM(CASE WHEN rt.type_name = 'Economy' THEN f.total_cost ELSE 0 END) AS economy_revenue,
|
|---|
| 176 | SUM(CASE WHEN rt.type_name = 'Standard Single' THEN f.total_cost ELSE 0 END) AS standard_single_revenue,
|
|---|
| 177 | SUM(CASE WHEN rt.type_name = 'Standard Double' THEN f.total_cost ELSE 0 END) AS standard_double_revenue,
|
|---|
| 178 | SUM(CASE WHEN rt.type_name = 'Deluxe Suite' THEN f.total_cost ELSE 0 END) AS deluxe_suite_revenue,
|
|---|
| 179 | SUM(CASE WHEN rt.type_name = 'VIP Penthouse' THEN f.total_cost ELSE 0 END) AS vip_penthouse_revenue,
|
|---|
| 180 | SUM(f.total_cost) AS total_revenue
|
|---|
| 181 | FROM FactReservation f
|
|---|
| 182 | JOIN DimHotel h ON h.hotel_key = f.hotel_key
|
|---|
| 183 | JOIN DimRoom dr ON dr.room_key = f.room_key
|
|---|
| 184 | JOIN DimRoomType rt ON rt.room_type_key = dr.room_type_key
|
|---|
| 185 | WHERE f.status != 'cancelled'
|
|---|
| 186 | GROUP BY h.hotel_name
|
|---|
| 187 | ORDER BY h.hotel_name;
|
|---|
| 188 |
|
|---|
| 189 | -- 8) Slicing - fiksiranje na vrednost na edna dimenzija - hotel i pregled na preostanatite dimenzii
|
|---|
| 190 |
|
|---|
| 191 | SELECT
|
|---|
| 192 | d.month_name,
|
|---|
| 193 | s.species_name,
|
|---|
| 194 | COUNT(*) AS reservations,
|
|---|
| 195 | SUM(f.total_cost) AS revenue
|
|---|
| 196 | FROM FactReservation f
|
|---|
| 197 | JOIN DimDate d ON d.date_key = f.date_key
|
|---|
| 198 | JOIN DimHotel h ON h.hotel_key = f.hotel_key
|
|---|
| 199 | JOIN DimPet p ON p.pet_key = f.pet_key
|
|---|
| 200 | JOIN DimSpecies s ON p.species_key = s.species_key
|
|---|
| 201 | WHERE h.hotel_name = 'Fur Haven'
|
|---|
| 202 | AND d.year = 2022
|
|---|
| 203 | AND f.status != 'cancelled'
|
|---|
| 204 | GROUP BY d.month_name, d.month_num, s.species_name
|
|---|
| 205 | ORDER BY d.month_num, s.species_name;
|
|---|
| 206 |
|
|---|
| 207 |
|
|---|
| 208 | -- 9) Dicing - fiksiranje na vrednosti na povekje dimenzii (4) - hotel, vid na milenice, seozna i status i pregled na preostanatite dimenzii
|
|---|
| 209 | SELECT
|
|---|
| 210 | d.month_name,
|
|---|
| 211 | rt.type_name AS room_type,
|
|---|
| 212 | COUNT(*) AS reservations,
|
|---|
| 213 | SUM(f.total_cost) AS revenue
|
|---|
| 214 | FROM FactReservation f
|
|---|
| 215 | JOIN DimDate d ON d.date_key = f.date_key
|
|---|
| 216 | JOIN DimHotel h ON h.hotel_key = f.hotel_key
|
|---|
| 217 | JOIN DimPet p ON p.pet_key = f.pet_key
|
|---|
| 218 | JOIN DimSpecies s ON p.species_key = s.species_key
|
|---|
| 219 | JOIN DimRoom dr ON dr.room_key = f.room_key
|
|---|
| 220 | JOIN DimRoomType rt ON rt.room_type_key = dr.room_type_key
|
|---|
| 221 | WHERE h.hotel_name = 'Fur Haven'
|
|---|
| 222 | AND d.season = 'Summer'
|
|---|
| 223 | AND s.species_name = 'Dog'
|
|---|
| 224 | AND f.status != 'cancelled'
|
|---|
| 225 | GROUP BY d.month_name, d.month_num, rt.type_name
|
|---|
| 226 | ORDER BY d.month_num, rt.type_name;
|
|---|