| Version 11 (modified by , 5 weeks ago) ( diff ) |
|---|
Напредни извештаи од базата (PostgreSQL)
Оваа страна прикажува 3 покомплексни извештаи.
Извршени се SQL надградбите (views, triggers, function, indexes) преку Node:
cd backend npm run db:apply
"Enhancements applied (views, triggers, function, indexes)."
Потоа внесовме мал демо-сет:
npm run db:seed
Seed done. User IDs: { ana: '12', bojan: '13', ciro: '14', classId: '7' }
1) Топ потрошувачи (пакети + мерч) со рангирање
Цел: По корисник, колку потрошил (сума на пакети + мерч) и кој му е рангот според вкупниот трошок.
Користен поглед: vw_user_spend
SQL:
SELECT user_id, username, email,
spend_packages, spend_merch, total_spend,
RANK() OVER (ORDER BY total_spend DESC) AS spend_rank
FROM vw_user_spend
ORDER BY total_spend DESC, user_id;
Релациска алгебра:
Π_{user_id,username,email,spend_packages,spend_merch,total_spend}
( User ⟕ (γ_{user_id; SUM(price)→spend_packages}(User_Purchased_Package ⋈ Package))
⟕ (γ_{user_id; SUM(price)→spend_merch}(User_Purchased_Merch ⋈ Merch_Items)) )
Извршување:
npm run db:reports
[
{
"user_id": "8",
"username": "mikiYoga",
"email": "miki@example.com",
"spend_packages": "45.00",
"spend_merch": "12.00",
"total_spend": "57.00",
"spend_rank": "1"
},...
]
2) Исполнетост на часови со дневно рангирање
Цел: За секој час: booked/capacity (во %) и ранг за истиот ден.
Користен поглед: vw_class_utilization
SQL:
SELECT *,
DENSE_RANK() OVER (PARTITION BY date ORDER BY utilization_pct DESC NULLS LAST) AS daily_rank
FROM vw_class_utilization
ORDER BY date, start_time, class_id;
Релациска алгебра:
γ_{class_id; COUNT(user_id)→booked}(Class ⟕ User_Booked_Class)
+ калкулација utilization_pct = booked / capacity
[
{
"class_id": "5",
"date": "2025-06-09T22:00:00.000Z",
"start_time": "08:00:00",
"end_time": "09:00:00",
"location": "Studio A",
"capacity": 20,
"booked": "1",
"utilization_pct": "5.00",
"instructor_id": "5",
"daily_rank": "2"
},...
]
3) Популарност на тренинзи по месец
Цел: По месец, броиме уникатни корисници кои резервирале часови што содржат даден тренинг; даваме месечен ранг.
Користен поглед: vw_training_pop_monthly
SQL:
SELECT training_id, training_name, month, num_bookings,
RANK() OVER (PARTITION BY month ORDER BY num_bookings DESC NULLS LAST) AS rank_in_month
FROM vw_training_pop_monthly
ORDER BY month DESC, rank_in_month, training_name;
Релациска алгебра:
γ_{training_id,month; COUNT(DISTINCT user_id)→num_bookings}
( Training ⋈ Class_Includes_Training ⋈ Class ⟕ User_Booked_Class )
[
{
"training_id": "7",
"training_name": "Vinyasa",
"month": "2025-08-31T22:00:00.000Z",
"num_bookings": "1",
"rank_in_month": "1"
},...
]
4) EXPLAIN/ANALYZE (за индекси)
Генерираме JSON планови:
npm run db:explain
A) За листање на настани, очекуваме користење на составниот индекс (date,time):
- Датотека:
backend/proofs/events_explain.json - Конзолата печати „Index Scan / Bitmap“ јазли ако ги има.
B) За броење на резервации по час, очекуваме idx_class_date_time и idx_ubc_class:
- Датотека:
backend/proofs/class_bookings_explain.json
{
"Plan": {
"Node Type": "Index Scan",
"Parallel Aware": false,
"Async Capable": false,
"Scan Direction": "Forward",
"Index Name": "idx_event_date_time",
...
}
{
"Node Type": "Index Scan",
"Parent Relationship": "Outer",
"Parallel Aware": false,
"Async Capable": false,
"Scan Direction": "Forward",
"Index Name": "idx_class_date_time",
...
}
