NaprednaTema: Analitiki.sql

File Analitiki.sql, 28.3 KB (added by 231004, 3 days ago)
Line 
1BEGIN;
2
3DROP SCHEMA IF EXISTS car_dealership_analytics CASCADE;
4CREATE SCHEMA car_dealership_analytics;
5
6SET search_path TO car_dealership_analytics, car_dealership;
7
8CREATE TABLE DimDate
9(
10 date_key INT PRIMARY KEY,
11 full_date DATE NOT NULL UNIQUE,
12 year INT NOT NULL,
13 quarter INT NOT NULL CHECK (quarter BETWEEN 1 AND 4),
14 month INT NOT NULL CHECK (month BETWEEN 1 AND 12),
15 month_name VARCHAR(20) NOT NULL,
16 day INT NOT NULL CHECK (day BETWEEN 1 AND 31),
17 day_of_week INT NOT NULL CHECK (day_of_week BETWEEN 1 AND 7),
18 day_name VARCHAR(20) NOT NULL,
19 is_weekend BOOLEAN NOT NULL
20);
21
22INSERT INTO DimDate
23SELECT TO_CHAR(d, 'YYYYMMDD')::INT AS date_key,
24 d::DATE AS full_date,
25 EXTRACT(YEAR FROM d)::INT AS year,
26 EXTRACT(QUARTER FROM d)::INT AS quarter,
27 EXTRACT(MONTH FROM d)::INT AS month,
28 TO_CHAR(d, 'FMMonth') AS month_name,
29 EXTRACT(DAY FROM d)::INT AS day,
30 EXTRACT(ISODOW FROM d)::INT AS day_of_week,
31 TO_CHAR(d, 'FMDay') AS day_name,
32 EXTRACT(ISODOW FROM d)::INT IN (6, 7) AS is_weekend
33FROM (SELECT generate_series(
34 COALESCE(MIN(date), CURRENT_DATE),
35 COALESCE(MAX(date), CURRENT_DATE),
36 INTERVAL '1 day'
37 )::DATE AS d
38 FROM car_dealership.Sale) dates;
39
40CREATE TABLE DimEmployee
41(
42 employee_key BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
43 employee_id INT NOT NULL UNIQUE,
44 employee_name VARCHAR(255) NOT NULL,
45 position VARCHAR(255) NOT NULL
46);
47
48INSERT INTO DimEmployee(employee_id, employee_name, position)
49SELECT e.id,
50 e.first_name || ' ' || e.last_name AS employee_name,
51 e.position
52FROM car_dealership.Employee e;
53
54CREATE TABLE DimCustomer
55(
56 customer_key BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
57 customer_id INT NOT NULL UNIQUE,
58 customer_name VARCHAR(255) NOT NULL,
59 email VARCHAR(255),
60 phone VARCHAR(20),
61 city VARCHAR(255),
62 country VARCHAR(255)
63);
64
65INSERT INTO DimCustomer(customer_id, customer_name, email, phone, city, country)
66SELECT DISTINCT ON (c.id) c.id,
67 c.first_name || ' ' || c.last_name AS customer_name,
68 c.email,
69 c.phone,
70 a.city,
71 a.country
72FROM car_dealership.Customer c
73 LEFT JOIN car_dealership.Address a
74 ON a.customer_id = c.id
75ORDER BY c.id, a.id;
76
77CREATE TABLE DimVehicle
78(
79 vehicle_key BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
80 vin VARCHAR(17) NOT NULL UNIQUE,
81 brand VARCHAR(255) NOT NULL,
82 model VARCHAR(255) NOT NULL,
83 model_year INT NOT NULL,
84 vehicle_type VARCHAR(255) NOT NULL,
85 color VARCHAR(255),
86 production_year INT,
87 base_price NUMERIC(12, 2)
88);
89
90INSERT INTO DimVehicle(vin, brand, model, model_year, vehicle_type, color, production_year, base_price)
91SELECT v.vin,
92 b.brand,
93 m.model,
94 m.year AS model_year,
95 vt.type AS vehicle_type,
96 v.color,
97 v.production_year,
98 v.price AS base_price
99FROM car_dealership.Vehicle v
100 JOIN car_dealership.Model m
101 ON m.id = v.model_id
102 JOIN car_dealership.Brand b
103 ON b.id = m.brand_id
104 JOIN car_dealership.VehicleType vt
105 ON vt.id = v.vehicle_type_id;
106
107CREATE TABLE DimPaymentType
108(
109 payment_type_key BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
110 payment_type VARCHAR(255) NOT NULL UNIQUE
111);
112
113INSERT INTO DimPaymentType(payment_type)
114SELECT DISTINCT type
115FROM car_dealership.Payment;
116
117CREATE TABLE DimContractType
118(
119 contract_type_key BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
120 contract_type VARCHAR(255) NOT NULL UNIQUE
121);
122
123INSERT INTO DimContractType(contract_type)
124SELECT DISTINCT type
125FROM car_dealership.Contract;
126
127CREATE TABLE FactSales
128(
129 sale_key BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
130 sale_id INT NOT NULL UNIQUE,
131 payment_id INT NOT NULL UNIQUE,
132
133 date_key INT NOT NULL,
134 employee_key BIGINT NOT NULL,
135 customer_key BIGINT NOT NULL,
136 vehicle_key BIGINT NOT NULL,
137 payment_type_key BIGINT NOT NULL,
138 contract_type_key BIGINT NOT NULL,
139
140 gross_revenue NUMERIC(12, 2) NOT NULL,
141 discount_percentage NUMERIC(5, 2) NOT NULL DEFAULT 0,
142 discount_amount NUMERIC(12, 2) NOT NULL DEFAULT 0,
143 net_revenue NUMERIC(12, 2) NOT NULL,
144 sale_count SMALLINT NOT NULL DEFAULT 1 CHECK (sale_count = 1),
145
146 CONSTRAINT fk_fact_date
147 FOREIGN KEY (date_key) REFERENCES DimDate (date_key),
148 CONSTRAINT fk_fact_employee
149 FOREIGN KEY (employee_key) REFERENCES DimEmployee (employee_key),
150 CONSTRAINT fk_fact_customer
151 FOREIGN KEY (customer_key) REFERENCES DimCustomer (customer_key),
152 CONSTRAINT fk_fact_vehicle
153 FOREIGN KEY (vehicle_key) REFERENCES DimVehicle (vehicle_key),
154 CONSTRAINT fk_fact_payment_type
155 FOREIGN KEY (payment_type_key) REFERENCES DimPaymentType (payment_type_key),
156 CONSTRAINT fk_fact_contract_type
157 FOREIGN KEY (contract_type_key) REFERENCES DimContractType (contract_type_key)
158);
159
160INSERT INTO FactSales(sale_id,
161 payment_id,
162 date_key,
163 employee_key,
164 customer_key,
165 vehicle_key,
166 payment_type_key,
167 contract_type_key,
168 gross_revenue,
169 discount_percentage,
170 discount_amount,
171 net_revenue,
172 sale_count)
173SELECT s.id AS sale_id,
174 p.id AS payment_id,
175 dd.date_key,
176 de.employee_key,
177 dc.customer_key,
178 dv.vehicle_key,
179 dpt.payment_type_key,
180 dct.contract_type_key,
181 p.amount AS gross_revenue,
182 COALESCE(d.percentage, 0)::NUMERIC(5, 2) AS discount_percentage,
183 ROUND(p.amount * COALESCE(d.percentage, 0) / 100.0, 2) AS discount_amount,
184 ROUND(p.amount * (1 - COALESCE(d.percentage, 0) / 100.0), 2) AS net_revenue,
185 1 AS sale_count
186FROM car_dealership.Sale s
187 JOIN car_dealership.Payment p
188 ON p.sale_id = s.id
189 JOIN car_dealership.Contract con
190 ON con.id = s.contract_id
191 JOIN DimDate dd
192 ON dd.full_date = s.date
193 JOIN DimEmployee de
194 ON de.employee_id = s.employee_id
195 JOIN DimCustomer dc
196 ON dc.customer_id = s.customer_id
197 JOIN DimVehicle dv
198 ON dv.vin = con.vin
199 JOIN DimPaymentType dpt
200 ON dpt.payment_type = p.type
201 JOIN DimContractType dct
202 ON dct.contract_type = con.type
203 LEFT JOIN car_dealership.Discount d
204 ON d.payment_id = p.id;
205
206CREATE INDEX idx_fact_sales_employee
207 ON FactSales (employee_key);
208
209CREATE INDEX idx_fact_sales_customer
210 ON FactSales (customer_key);
211
212CREATE INDEX idx_fact_sales_vehicle
213 ON FactSales (vehicle_key);
214
215CREATE INDEX idx_fact_sales_payment_type
216 ON FactSales (payment_type_key);
217
218CREATE INDEX idx_fact_sales_contract_type
219 ON FactSales (contract_type_key);
220
221CREATE INDEX idx_fact_sales_date_vehicle
222 ON FactSales (date_key, vehicle_key)
223 INCLUDE (gross_revenue, discount_amount, net_revenue, sale_count);
224
225CREATE INDEX idx_fact_sales_date_contract_type
226 ON FactSales (date_key, contract_type_key)
227 INCLUDE (gross_revenue, discount_amount, net_revenue, sale_count);
228
229CREATE INDEX idx_dim_date_year_month
230 ON DimDate (year, month);
231
232CREATE INDEX idx_dim_vehicle_brand_model
233 ON DimVehicle (brand, model);
234
235CREATE INDEX idx_dim_customer_city
236 ON DimCustomer (city);
237
238CREATE OR REPLACE VIEW RevenueByBrandAndYear AS
239SELECT dv.brand,
240 dd.year,
241 SUM(fs.gross_revenue) AS total_gross_revenue,
242 SUM(fs.discount_amount) AS total_discount_amount,
243 SUM(fs.net_revenue) AS total_net_revenue,
244 SUM(fs.sale_count) AS total_sales,
245 ROUND(AVG(fs.net_revenue), 2) AS avg_net_sale_value
246FROM FactSales fs
247 JOIN DimVehicle dv
248 ON dv.vehicle_key = fs.vehicle_key
249 JOIN DimDate dd
250 ON dd.date_key = fs.date_key
251GROUP BY dv.brand, dd.year;
252
253CREATE OR REPLACE VIEW RevenueByEmployeeAndMonth AS
254SELECT de.employee_id,
255 de.employee_name,
256 de.position,
257 dd.year,
258 dd.month,
259 MAKE_DATE(dd.year, dd.month, 1) AS month_start,
260 SUM(fs.gross_revenue) AS total_gross_revenue,
261 SUM(fs.discount_amount) AS total_discount_amount,
262 SUM(fs.net_revenue) AS total_net_revenue,
263 SUM(fs.sale_count) AS total_sales,
264 ROUND(AVG(fs.net_revenue), 2) AS avg_net_sale_value
265FROM FactSales fs
266 JOIN DimEmployee de
267 ON de.employee_key = fs.employee_key
268 JOIN DimDate dd
269 ON dd.date_key = fs.date_key
270GROUP BY de.employee_id, de.employee_name, de.position, dd.year, dd.month;
271
272CREATE OR REPLACE VIEW SalesByPaymentType AS
273SELECT dpt.payment_type,
274 SUM(fs.gross_revenue) AS total_gross_revenue,
275 SUM(fs.discount_amount) AS total_discount_amount,
276 SUM(fs.net_revenue) AS total_net_revenue,
277 SUM(fs.sale_count) AS total_sales,
278 ROUND(AVG(fs.net_revenue), 2) AS avg_net_sale_value,
279 ROUND(100.0 * SUM(fs.sale_count) / SUM(SUM(fs.sale_count)) OVER (), 2) AS sales_percentage
280FROM FactSales fs
281 JOIN DimPaymentType dpt
282 ON dpt.payment_type_key = fs.payment_type_key
283GROUP BY dpt.payment_type;
284
285CREATE OR REPLACE VIEW RevenueByCustomerCity AS
286SELECT dc.country,
287 dc.city,
288 SUM(fs.gross_revenue) AS total_gross_revenue,
289 SUM(fs.discount_amount) AS total_discount_amount,
290 SUM(fs.net_revenue) AS total_net_revenue,
291 SUM(fs.sale_count) AS total_sales,
292 ROUND(AVG(fs.net_revenue), 2) AS avg_net_sale_value
293FROM FactSales fs
294 JOIN DimCustomer dc
295 ON dc.customer_key = fs.customer_key
296GROUP BY dc.country, dc.city;
297
298CREATE OR REPLACE VIEW RevenueByVehicleType AS
299SELECT dv.vehicle_type,
300 SUM(fs.gross_revenue) AS total_gross_revenue,
301 SUM(fs.discount_amount) AS total_discount_amount,
302 SUM(fs.net_revenue) AS total_net_revenue,
303 SUM(fs.sale_count) AS total_sales,
304 ROUND(AVG(fs.net_revenue), 2) AS avg_net_sale_value
305FROM FactSales fs
306 JOIN DimVehicle dv
307 ON dv.vehicle_key = fs.vehicle_key
308GROUP BY dv.vehicle_type;
309
310CREATE OR REPLACE VIEW RevenueByContractType AS
311SELECT dct.contract_type,
312 SUM(fs.gross_revenue) AS total_gross_revenue,
313 SUM(fs.discount_amount) AS total_discount_amount,
314 SUM(fs.net_revenue) AS total_net_revenue,
315 SUM(fs.sale_count) AS total_sales,
316 ROUND(AVG(fs.net_revenue), 2) AS avg_net_sale_value
317FROM FactSales fs
318 JOIN DimContractType dct
319 ON dct.contract_type_key = fs.contract_type_key
320GROUP BY dct.contract_type;
321
322CREATE MATERIALIZED VIEW SalesCubeBrandYearPaymentContract AS
323SELECT CASE WHEN GROUPING(dv.brand) = 1 THEN 'All Brands' ELSE dv.brand END AS brand,
324 CASE WHEN GROUPING(dd.year) = 1 THEN 'All Years' ELSE dd.year::TEXT END AS year_label,
325 CASE WHEN GROUPING(dpt.payment_type) = 1 THEN 'All Payment Types' ELSE dpt.payment_type END AS payment_type,
326 CASE WHEN GROUPING(dct.contract_type) = 1 THEN 'All Contract Types' ELSE dct.contract_type END AS contract_type,
327 GROUPING(dv.brand) AS is_brand_total,
328 GROUPING(dd.year) AS is_year_total,
329 GROUPING(dpt.payment_type) AS is_payment_type_total,
330 GROUPING(dct.contract_type) AS is_contract_type_total,
331 SUM(fs.gross_revenue) AS total_gross_revenue,
332 SUM(fs.discount_amount) AS total_discount_amount,
333 SUM(fs.net_revenue) AS total_net_revenue,
334 SUM(fs.sale_count) AS total_sales,
335 ROUND(AVG(fs.net_revenue), 2) AS avg_net_sale_value
336FROM FactSales fs
337 JOIN DimVehicle dv
338 ON dv.vehicle_key = fs.vehicle_key
339 JOIN DimDate dd
340 ON dd.date_key = fs.date_key
341 JOIN DimPaymentType dpt
342 ON dpt.payment_type_key = fs.payment_type_key
343 JOIN DimContractType dct
344 ON dct.contract_type_key = fs.contract_type_key
345GROUP BY CUBE (dv.brand, dd.year, dpt.payment_type, dct.contract_type);
346
347CREATE INDEX idx_mv_sales_cube_brand_year_payment_contract
348 ON SalesCubeBrandYearPaymentContract (
349 brand,
350 year_label,
351 payment_type,
352 contract_type,
353 is_brand_total,
354 is_year_total,
355 is_payment_type_total,
356 is_contract_type_total
357 );
358
359CREATE OR REPLACE VIEW SalesCubeBrandYearPayment AS
360SELECT brand,
361 year_label,
362 payment_type,
363 is_brand_total,
364 is_year_total,
365 is_payment_type_total,
366 total_gross_revenue,
367 total_discount_amount,
368 total_net_revenue,
369 total_sales,
370 avg_net_sale_value
371FROM SalesCubeBrandYearPaymentContract
372WHERE is_contract_type_total = 1;
373
374CREATE MATERIALIZED VIEW EmployeeSalesRollup AS
375SELECT CASE WHEN GROUPING(de.position) = 1 THEN 'All Positions' ELSE de.position END AS position,
376 CASE
377 WHEN GROUPING(de.employee_id) = 1 THEN NULL
378 ELSE de.employee_id
379 END AS employee_id,
380 CASE
381 WHEN GROUPING(de.employee_name) = 1 THEN 'All Employees'
382 ELSE de.employee_name
383 END AS employee_name,
384 CASE WHEN GROUPING(dd.year) = 1 THEN 'All Years' ELSE dd.year::TEXT END AS year_label,
385 GROUPING(de.position) AS is_position_total,
386 GROUPING(de.employee_id) AS is_employee_total,
387 GROUPING(dd.year) AS is_year_total,
388 SUM(fs.gross_revenue) AS total_gross_revenue,
389 SUM(fs.discount_amount) AS total_discount_amount,
390 SUM(fs.net_revenue) AS total_net_revenue,
391 SUM(fs.sale_count) AS total_sales,
392 ROUND(AVG(fs.net_revenue), 2) AS avg_net_sale_value
393FROM FactSales fs
394 JOIN DimEmployee de
395 ON de.employee_key = fs.employee_key
396 JOIN DimDate dd
397 ON dd.date_key = fs.date_key
398GROUP BY GROUPING SETS
399 ( (de.position, de.employee_id, de.employee_name, dd.year),
400 (de.position, dd.year),
401 (dd.year),
402 (de.position, de.employee_id, de.employee_name),
403 (de.position),
404 ()
405 );
406
407CREATE INDEX idx_mv_employee_sales_rollup
408 ON EmployeeSalesRollup (
409 position,
410 employee_id,
411 year_label,
412 is_position_total,
413 is_employee_total,
414 is_year_total
415 );
416
417CREATE OR REPLACE VIEW EmployeeCubePositionEmployeeYear AS
418SELECT position,
419 employee_id,
420 employee_name,
421 year_label,
422 is_position_total,
423 is_employee_total,
424 is_year_total,
425 total_gross_revenue,
426 total_discount_amount,
427 total_net_revenue,
428 total_sales,
429 avg_net_sale_value
430FROM EmployeeSalesRollup;
431
432CREATE MATERIALIZED VIEW VehicleCubeTypeBrandYear AS
433SELECT CASE WHEN GROUPING(dv.vehicle_type) = 1 THEN 'All Vehicle Types' ELSE dv.vehicle_type END AS vehicle_type,
434 CASE WHEN GROUPING(dv.brand) = 1 THEN 'All Brands' ELSE dv.brand END AS brand,
435 CASE WHEN GROUPING(dd.year) = 1 THEN 'All Years' ELSE dd.year::TEXT END AS year_label,
436 GROUPING(dv.vehicle_type) AS is_vehicle_type_total,
437 GROUPING(dv.brand) AS is_brand_total,
438 GROUPING(dd.year) AS is_year_total,
439 SUM(fs.gross_revenue) AS total_gross_revenue,
440 SUM(fs.discount_amount) AS total_discount_amount,
441 SUM(fs.net_revenue) AS total_net_revenue,
442 SUM(fs.sale_count) AS total_sales,
443 ROUND(AVG(fs.net_revenue), 2) AS avg_net_sale_value
444FROM FactSales fs
445 JOIN DimVehicle dv
446 ON dv.vehicle_key = fs.vehicle_key
447 JOIN DimDate dd
448 ON dd.date_key = fs.date_key
449GROUP BY CUBE (dv.vehicle_type, dv.brand, dd.year);
450
451CREATE INDEX idx_mv_vehicle_cube_type_brand_year
452 ON VehicleCubeTypeBrandYear (
453 vehicle_type,
454 brand,
455 year_label,
456 is_vehicle_type_total,
457 is_brand_total,
458 is_year_total
459 );
460
461ANALYZE DimDate;
462ANALYZE DimEmployee;
463ANALYZE DimCustomer;
464ANALYZE DimVehicle;
465ANALYZE DimPaymentType;
466ANALYZE DimContractType;
467ANALYZE FactSales;
468ANALYZE SalesCubeBrandYearPaymentContract;
469ANALYZE EmployeeSalesRollup;
470ANALYZE VehicleCubeTypeBrandYear;
471
472COMMIT;
473
474SELECT *
475FROM RevenueByBrandAndYear
476ORDER BY total_net_revenue DESC
477LIMIT 20;
478
479SELECT *
480FROM RevenueByEmployeeAndMonth
481ORDER BY total_net_revenue DESC
482LIMIT 20;
483
484SELECT *
485FROM SalesByPaymentType
486ORDER BY total_net_revenue DESC;
487
488SELECT *
489FROM RevenueByContractType
490ORDER BY total_net_revenue DESC;
491
492SELECT *
493FROM RevenueByCustomerCity
494ORDER BY total_net_revenue DESC
495LIMIT 20;
496
497SELECT *
498FROM SalesCubeBrandYearPaymentContract
499ORDER BY total_net_revenue DESC NULLS LAST
500LIMIT 50;
501
502SELECT *
503FROM EmployeeSalesRollup
504ORDER BY total_net_revenue DESC NULLS LAST
505LIMIT 50;
506
507SELECT *
508FROM VehicleCubeTypeBrandYear
509ORDER BY total_net_revenue DESC NULLS LAST
510LIMIT 50;
511
512
513-- =========================================================
514-- OPTIONAL VALIDATION AND INDEX ANALYSIS
515-- Run after the Data Cube build finishes.
516-- =========================================================
517
518SET search_path TO car_dealership_analytics, car_dealership;
519
520-- Refresh statistics after the large analytical load.
521VACUUM ANALYZE FactSales;
522VACUUM ANALYZE DimDate;
523VACUUM ANALYZE DimEmployee;
524VACUUM ANALYZE DimCustomer;
525VACUUM ANALYZE DimVehicle;
526VACUUM ANALYZE DimPaymentType;
527VACUUM ANALYZE DimContractType;
528VACUUM ANALYZE SalesCubeBrandYearPaymentContract;
529VACUUM ANALYZE EmployeeSalesRollup;
530VACUUM ANALYZE VehicleCubeTypeBrandYear;
531
532
533-- =========================================================
534-- GLOBAL FACT CHECK
535-- Confirms one fact row equals one sale, and revenue math is consistent.
536-- Expected: fact_rows = total_sales and gross_revenue - discount_amount = net_revenue.
537-- =========================================================
538
539SELECT COUNT(*) AS fact_rows,
540 SUM(sale_count) AS total_sales,
541 SUM(gross_revenue) AS gross_revenue,
542 SUM(discount_amount) AS discount_amount,
543 SUM(net_revenue) AS net_revenue,
544 SUM(gross_revenue) - SUM(discount_amount) AS calculated_net_revenue
545FROM FactSales;
546
547
548-- =========================================================
549-- INDEX USAGE CHECKS
550-- Look for Index Scan, Bitmap Index Scan, or Index Only Scan in the output.
551-- =========================================================
552
553EXPLAIN (ANALYZE, BUFFERS)
554SELECT *
555FROM FactSales
556WHERE employee_key = (SELECT employee_key
557 FROM FactSales
558 LIMIT 1);
559-- Checks idx_fact_sales_employee.
560
561EXPLAIN (ANALYZE, BUFFERS)
562SELECT *
563FROM FactSales
564WHERE customer_key = (SELECT customer_key
565 FROM FactSales
566 LIMIT 1);
567-- Checks idx_fact_sales_customer.
568
569EXPLAIN (ANALYZE, BUFFERS)
570SELECT *
571FROM FactSales
572WHERE vehicle_key = (SELECT vehicle_key
573 FROM FactSales
574 LIMIT 1);
575-- Checks idx_fact_sales_vehicle.
576
577EXPLAIN (ANALYZE, BUFFERS)
578SELECT *
579FROM FactSales
580WHERE payment_type_key = (SELECT payment_type_key
581 FROM FactSales
582 LIMIT 1);
583-- Checks idx_fact_sales_payment_type.
584
585EXPLAIN (ANALYZE, BUFFERS)
586SELECT *
587FROM FactSales
588WHERE contract_type_key = (SELECT contract_type_key
589 FROM FactSales
590 LIMIT 1);
591-- Checks idx_fact_sales_contract_type.
592
593EXPLAIN (ANALYZE, BUFFERS)
594SELECT gross_revenue, discount_amount, net_revenue, sale_count
595FROM FactSales
596WHERE (date_key, vehicle_key) = (SELECT date_key, vehicle_key
597 FROM FactSales
598 LIMIT 1);
599-- Checks idx_fact_sales_date_vehicle. Index Only Scan shows the INCLUDE columns helped.
600
601EXPLAIN (ANALYZE, BUFFERS)
602SELECT gross_revenue, discount_amount, net_revenue, sale_count
603FROM FactSales
604WHERE (date_key, contract_type_key) = (SELECT date_key, contract_type_key
605 FROM FactSales
606 LIMIT 1);
607-- Checks idx_fact_sales_date_contract_type. Index Only Scan shows the INCLUDE columns helped.
608
609EXPLAIN (ANALYZE, BUFFERS)
610SELECT *
611FROM DimDate
612WHERE (year, month) = (SELECT year, month
613 FROM DimDate
614 LIMIT 1);
615-- Checks idx_dim_date_year_month.
616
617EXPLAIN (ANALYZE, BUFFERS)
618SELECT *
619FROM DimVehicle
620WHERE (brand, model) = (SELECT brand, model
621 FROM DimVehicle
622 LIMIT 1);
623-- Checks idx_dim_vehicle_brand_model.
624
625EXPLAIN (ANALYZE, BUFFERS)
626SELECT *
627FROM DimCustomer
628WHERE city = (SELECT city
629 FROM DimCustomer
630 WHERE city IS NOT NULL
631 LIMIT 1);
632-- Checks idx_dim_customer_city.
633
634EXPLAIN (ANALYZE, BUFFERS)
635SELECT *
636FROM SalesCubeBrandYearPaymentContract
637WHERE (brand, year_label, payment_type, contract_type) = (SELECT brand, year_label, payment_type, contract_type
638 FROM SalesCubeBrandYearPaymentContract
639 WHERE is_brand_total = 0
640 AND is_year_total = 0
641 AND is_payment_type_total = 0
642 AND is_contract_type_total = 0
643 LIMIT 1);
644-- Checks idx_mv_sales_cube_brand_year_payment_contract.
645
646EXPLAIN (ANALYZE, BUFFERS)
647SELECT *
648FROM EmployeeSalesRollup
649WHERE (position, employee_id, year_label) = (SELECT position, employee_id, year_label
650 FROM EmployeeSalesRollup
651 WHERE is_position_total = 0
652 AND is_employee_total = 0
653 AND is_year_total = 0
654 LIMIT 1);
655-- Checks idx_mv_employee_sales_rollup.
656
657EXPLAIN (ANALYZE, BUFFERS)
658SELECT *
659FROM VehicleCubeTypeBrandYear
660WHERE (vehicle_type, brand, year_label) = (SELECT vehicle_type, brand, year_label
661 FROM VehicleCubeTypeBrandYear
662 WHERE is_vehicle_type_total = 0
663 AND is_brand_total = 0
664 AND is_year_total = 0
665 LIMIT 1);
666-- Checks idx_mv_vehicle_cube_type_brand_year.
667
668
669-- =========================================================
670-- INDEX BENEFIT CHECK TEMPLATE
671-- Use this pattern for any index. ROLLBACK restores the dropped index.
672-- Compare Execution Time and Buffers before and after DROP INDEX.
673-- =========================================================
674
675BEGIN;
676
677EXPLAIN (ANALYZE, BUFFERS)
678SELECT *
679FROM FactSales
680WHERE employee_key = (SELECT employee_key
681 FROM FactSales
682 LIMIT 1);
683
684DROP INDEX idx_fact_sales_employee;
685
686EXPLAIN (ANALYZE, BUFFERS)
687SELECT *
688FROM FactSales
689WHERE employee_key = (SELECT employee_key
690 FROM FactSales
691 LIMIT 1);
692
693ROLLBACK;
694
695
696-- =========================================================
697-- VIEW VALIDATION CHECKS
698-- Manual totals should match the corresponding view/materialized view totals.
699-- =========================================================
700
701SELECT *
702FROM RevenueByBrandAndYear
703ORDER BY total_net_revenue DESC
704LIMIT 20;
705
706SELECT dv.brand,
707 dd.year,
708 SUM(fs.gross_revenue) AS total_gross_revenue,
709 SUM(fs.discount_amount) AS total_discount_amount,
710 SUM(fs.net_revenue) AS total_net_revenue,
711 SUM(fs.sale_count) AS total_sales,
712 ROUND(AVG(fs.net_revenue), 2) AS avg_net_sale_value
713FROM FactSales fs
714 JOIN DimVehicle dv ON dv.vehicle_key = fs.vehicle_key
715 JOIN DimDate dd ON dd.date_key = fs.date_key
716GROUP BY dv.brand, dd.year
717ORDER BY total_net_revenue DESC
718LIMIT 20;
719
720SELECT total_net_revenue, total_sales
721FROM SalesCubeBrandYearPaymentContract
722WHERE is_brand_total = 1
723 AND is_year_total = 1
724 AND is_payment_type_total = 1
725 AND is_contract_type_total = 1;
726
727SELECT SUM(net_revenue) AS total_net_revenue,
728 SUM(sale_count) AS total_sales
729FROM FactSales;