| 6 | | == Complex DB Reports (SQL, Stored Procedures, Relational Algebra) |
| | 17 | == Implementation / Examples == |
| | 18 | |
| | 19 | === 1) Complex Reports === |
| | 20 | Complex reports combine data from multiple tables and return analytical information that is useful for managing weddings. |
| | 21 | In our Wedding Planner system, reports are useful for guest status tracking, cost breakdown, scheduling and venue usage. |
| | 22 | |
| | 23 | ==== Example 1: Total guests and RSVP status per wedding ==== |
| | 24 | This query returns the total number of guests per wedding, and how many RSVPs are CONFIRMED vs CANCELLED. |
| | 25 | |
| | 26 | {{{ |
| | 27 | SELECT |
| | 28 | w.wedding_id, |
| | 29 | w.date AS wedding_date, |
| | 30 | COUNT(DISTINCT g.guest_id) AS total_guests, |
| | 31 | COUNT(CASE WHEN r.status = 'CONFIRMED' THEN 1 END) AS confirmed_guests, |
| | 32 | COUNT(CASE WHEN r.status = 'CANCELLED' THEN 1 END) AS cancelled_guests |
| | 33 | FROM wedding w |
| | 34 | LEFT JOIN guest g ON w.wedding_id = g.wedding_id |
| | 35 | LEFT JOIN event e ON w.wedding_id = e.wedding_id |
| | 36 | LEFT JOIN event_rsvp r ON e.event_id = r.event_id AND g.guest_id = r.guest_id |
| | 37 | GROUP BY w.wedding_id, w.date; |
| | 38 | }}} |
| | 39 | |
| | 40 | *Purpose:* Helps the wedding owner see how many guests are invited and their RSVP status. |
| | 41 | |
| | 42 | ==== Example 2: Costs per wedding (venue + band + photographer) ==== |
| | 43 | This report computes the cost of a wedding by summing the cost of booked providers. |
| | 44 | |
| | 45 | {{{ |
| | 46 | SELECT |
| | 47 | w.wedding_id, |
| | 48 | w.date, |
| | 49 | COALESCE(SUM(vb.price), 0) AS venue_cost, |
| | 50 | COALESCE(SUM(EXTRACT(EPOCH FROM (bb.end_time - bb.start_time))/3600 * b.price_per_hour), 0) AS band_cost, |
| | 51 | COALESCE(SUM(EXTRACT(EPOCH FROM (pb.end_time - pb.start_time))/3600 * p.price_per_hour), 0) AS photographer_cost |
| | 52 | FROM wedding w |
| | 53 | LEFT JOIN venue_booking vb ON w.wedding_id = vb.wedding_id |
| | 54 | LEFT JOIN band_booking bb ON w.wedding_id = bb.wedding_id |
| | 55 | LEFT JOIN band b ON bb.band_id = b.band_id |
| | 56 | LEFT JOIN photographer_booking pb ON w.wedding_id = pb.wedding_id |
| | 57 | LEFT JOIN photographer p ON pb.photographer_id = p.photographer_id |
| | 58 | GROUP BY w.wedding_id, w.date; |
| | 59 | }}} |
| | 60 | |
| | 61 | *Purpose:* Gives a clear financial summary for budgeting and comparing providers. |
| | 62 | |
| | 63 | ==== Example 3: Venue utilization (capacity report) ==== |
| | 64 | This query checks how many guests are seated, and how many free seats are still available at the booked venue. |
| | 65 | |
| | 66 | {{{ |
| | 67 | SELECT |
| | 68 | v.name AS venue_name, |
| | 69 | v.capacity, |
| | 70 | w.wedding_id, |
| | 71 | COUNT(a.guest_id) AS seated_guests, |
| | 72 | (v.capacity - COUNT(a.guest_id)) AS free_seats |
| | 73 | FROM venue v |
| | 74 | JOIN venue_booking vb ON v.venue_id = vb.venue_id |
| | 75 | JOIN wedding w ON vb.wedding_id = w.wedding_id |
| | 76 | LEFT JOIN attendance a ON a.event_id IN ( |
| | 77 | SELECT event_id FROM event WHERE wedding_id = w.wedding_id |
| | 78 | ) |
| | 79 | GROUP BY v.name, v.capacity, w.wedding_id; |
| | 80 | }}} |
| | 81 | |
| | 82 | *Purpose:* Useful to see if the wedding has exceeded the venue capacity or still has room. |
| | 83 | |
| | 84 | ==== Example 4: Temporal distribution of events ==== |
| | 85 | This query returns the schedule of events ordered by date and time. |
| | 86 | |
| | 87 | {{{ |
| | 88 | SELECT |
| | 89 | w.wedding_id, |
| | 90 | e.event_type, |
| | 91 | e.date, |
| | 92 | e.start_time, |
| | 93 | e.end_time, |
| | 94 | EXTRACT(EPOCH FROM (e.end_time - e.start_time))/3600 AS duration_hours |
| | 95 | FROM wedding w |
| | 96 | JOIN event e ON w.wedding_id = e.wedding_id |
| | 97 | ORDER BY e.date, e.start_time; |
| | 98 | }}} |
| | 99 | |
| | 100 | *Purpose:* Helps planning timelines and checking event overlaps in the schedule. |
| | 101 | |
| | 102 | === 2) Stored Procedures === |
| | 103 | Stored procedures allow us to encapsulate database logic into reusable functions that can be called when needed. |
| | 104 | They reduce repetition and help organize logic for reporting and automation. |
| | 105 | |
| | 106 | ==== Example 1: Total wedding cost ==== |
| | 107 | This procedure calculates the full total cost of a wedding (venue + band + photographer). |
| | 108 | |
| | 109 | {{{ |
| | 110 | CREATE OR REPLACE PROCEDURE wedding_total_cost( |
| | 111 | IN p_wedding_id INT, |
| | 112 | OUT total_cost NUMERIC |
| | 113 | ) |
| | 114 | LANGUAGE plpgsql |
| | 115 | AS $$ |
| | 116 | BEGIN |
| | 117 | SELECT |
| | 118 | COALESCE(SUM(vb.price),0) |
| | 119 | + COALESCE(SUM(EXTRACT(EPOCH FROM (bb.end_time - bb.start_time))/3600 * b.price_per_hour),0) |
| | 120 | + COALESCE(SUM(EXTRACT(EPOCH FROM (pb.end_time - pb.start_time))/3600 * p.price_per_hour),0) |
| | 121 | INTO total_cost |
| | 122 | FROM wedding w |
| | 123 | LEFT JOIN venue_booking vb ON w.wedding_id = vb.wedding_id |
| | 124 | LEFT JOIN band_booking bb ON w.wedding_id = bb.wedding_id |
| | 125 | LEFT JOIN band b ON bb.band_id = b.band_id |
| | 126 | LEFT JOIN photographer_booking pb ON w.wedding_id = pb.wedding_id |
| | 127 | LEFT JOIN photographer p ON pb.photographer_id = p.photographer_id |
| | 128 | WHERE w.wedding_id = p_wedding_id; |
| | 129 | END; |
| | 130 | $$; |
| | 131 | }}} |
| | 132 | |
| | 133 | *Purpose:* Gives one clear number for budgeting and reports. |