| | 475 | |
| | 476 | |
| | 477 | = Venue Capacity Utilization Analysis = |
| | 478 | |
| | 479 | == 2. Scenario Overview == |
| | 480 | |
| | 481 | This scenario analyzes venue occupancy and attendance utilization across weddings. |
| | 482 | |
| | 483 | The analysis combines: |
| | 484 | * venue capacity |
| | 485 | * confirmed attendance |
| | 486 | * actual attendance |
| | 487 | * booking information |
| | 488 | * occupancy percentages |
| | 489 | |
| | 490 | The report enables: |
| | 491 | * occupancy monitoring |
| | 492 | * capacity validation |
| | 493 | * venue efficiency analysis |
| | 494 | * utilization categorization |
| | 495 | * operational planning |
| | 496 | |
| | 497 | == 2.1 Objective == |
| | 498 | |
| | 499 | Analyze the relationship between confirmed guest attendance and venue capacity constraints. |
| | 500 | |
| | 501 | This report determines the occupancy rate, identifies capacity violations, and provides venue utilization metrics across weddings. |
| | 502 | |
| | 503 | The analysis combines attendance records, venue specifications, and booking confirmations to establish operational efficiency indicators. |
| | 504 | |
| | 505 | == 2.2 SQL Query Implementation == |
| | 506 | |
| | 507 | === SQL Code === |
| | 508 | |
| | 509 | {{{ |
| | 510 | #!sql |
| | 511 | SELECT |
| | 512 | v.venue_id, |
| | 513 | v.name AS venue_name, |
| | 514 | v.capacity AS venue_capacity, |
| | 515 | |
| | 516 | w.wedding_id, |
| | 517 | |
| | 518 | u.first_name || ' ' || u.last_name |
| | 519 | AS organizer_name, |
| | 520 | |
| | 521 | w.date AS wedding_date, |
| | 522 | |
| | 523 | COUNT(DISTINCT a.guest_id) |
| | 524 | AS confirmed_attendees, |
| | 525 | |
| | 526 | COUNT(DISTINCT CASE |
| | 527 | WHEN a.status = 'ATTENDED' |
| | 528 | THEN a.guest_id |
| | 529 | END) AS actual_attendance, |
| | 530 | |
| | 531 | v.capacity - COUNT(DISTINCT a.guest_id) |
| | 532 | AS available_seats, |
| | 533 | |
| | 534 | ROUND( |
| | 535 | ( |
| | 536 | CAST(COUNT(DISTINCT a.guest_id) AS NUMERIC) |
| | 537 | / v.capacity |
| | 538 | ) * 100, |
| | 539 | 2 |
| | 540 | ) AS occupancy_rate_percent, |
| | 541 | |
| | 542 | CASE |
| | 543 | WHEN COUNT(DISTINCT a.guest_id) > v.capacity |
| | 544 | THEN 'EXCEEDED' |
| | 545 | |
| | 546 | WHEN COUNT(DISTINCT a.guest_id) |
| | 547 | >= (v.capacity * 0.9) |
| | 548 | THEN 'HIGH' |
| | 549 | |
| | 550 | WHEN COUNT(DISTINCT a.guest_id) |
| | 551 | >= (v.capacity * 0.6) |
| | 552 | THEN 'MODERATE' |
| | 553 | |
| | 554 | ELSE 'LOW' |
| | 555 | END AS utilization_category, |
| | 556 | |
| | 557 | vb.status AS booking_status, |
| | 558 | vb.date AS booking_date |
| | 559 | |
| | 560 | FROM venue v |
| | 561 | |
| | 562 | INNER JOIN venue_booking vb |
| | 563 | ON v.venue_id = vb.venue_id |
| | 564 | |
| | 565 | INNER JOIN wedding w |
| | 566 | ON vb.wedding_id = w.wedding_id |
| | 567 | |
| | 568 | INNER JOIN "user" u |
| | 569 | ON w.user_id = u.user_id |
| | 570 | |
| | 571 | LEFT JOIN event e |
| | 572 | ON w.wedding_id = e.wedding_id |
| | 573 | |
| | 574 | LEFT JOIN attendance a |
| | 575 | ON e.event_id = a.event_id |
| | 576 | AND a.status IN ('ATTENDED', 'CONFIRMED') |
| | 577 | |
| | 578 | GROUP BY |
| | 579 | v.venue_id, |
| | 580 | v.name, |
| | 581 | v.capacity, |
| | 582 | w.wedding_id, |
| | 583 | u.first_name, |
| | 584 | u.last_name, |
| | 585 | w.date, |
| | 586 | vb.status, |
| | 587 | vb.date |
| | 588 | |
| | 589 | HAVING COUNT(DISTINCT a.guest_id) > 0 |
| | 590 | |
| | 591 | ORDER BY |
| | 592 | v.venue_id, |
| | 593 | w.wedding_id; |
| | 594 | }}} |
| | 595 | |
| | 596 | == 2.3 Query Complexity Analysis == |
| | 597 | |
| | 598 | * Join Count: 6 tables |
| | 599 | * Join Types: |
| | 600 | * INNER JOIN |
| | 601 | * LEFT JOIN |
| | 602 | |
| | 603 | * Aggregate Functions: |
| | 604 | * COUNT(DISTINCT ...) |
| | 605 | * ROUND() |
| | 606 | * CASE |
| | 607 | |
| | 608 | * Filtering: |
| | 609 | * HAVING clause after aggregation |
| | 610 | |
| | 611 | * Operational Metrics: |
| | 612 | * occupancy rate |
| | 613 | * available seats |
| | 614 | * utilization category |
| | 615 | |
| | 616 | == 2.4 Relational Algebra Expression == |
| | 617 | |
| | 618 | {{{ |
| | 619 | π( |
| | 620 | v.venue_id, |
| | 621 | v.name, |
| | 622 | v.capacity, |
| | 623 | w.wedding_id, |
| | 624 | u.fname, |
| | 625 | u.lname, |
| | 626 | w.date, |
| | 627 | COUNT(a.guest_id) |
| | 628 | ) |
| | 629 | |
| | 630 | ( |
| | 631 | σ(COUNT(guest_id) > 0) |
| | 632 | |
| | 633 | ( |
| | 634 | γ( |
| | 635 | venue_id, |
| | 636 | wedding_id, |
| | 637 | COUNT(DISTINCT a.guest_id) |
| | 638 | ) |
| | 639 | |
| | 640 | ( |
| | 641 | (((Venue ⟕ Venue_Booking) |
| | 642 | ⟕ Wedding) |
| | 643 | ⟕ User) |
| | 644 | ⟕ Event) |
| | 645 | ⟕ Attendance |
| | 646 | ) |
| | 647 | ) |
| | 648 | }}} |
| | 649 | |
| | 650 | === Notation === |
| | 651 | |
| | 652 | * π = Projection |
| | 653 | * σ = Selection |
| | 654 | * γ = Grouping and aggregation |
| | 655 | * ⟕ = Join operation |
| | 656 | |
| | 657 | === Interpretation === |
| | 658 | |
| | 659 | The expression combines venue, wedding, event, and attendance relations to calculate occupancy metrics and venue utilization statistics. |
| | 660 | |
| | 661 | == 2.5 PostgreSQL Stored Procedure == |
| | 662 | |
| | 663 | === SQL Code === |
| | 664 | |
| | 665 | {{{ |
| | 666 | #!sql |
| | 667 | CREATE OR REPLACE PROCEDURE venue_capacity_utilization_report( |
| | 668 | IN p_venue_id INT DEFAULT NULL, |
| | 669 | IN p_min_occupancy_percent NUMERIC DEFAULT 0, |
| | 670 | IN p_max_occupancy_percent NUMERIC DEFAULT 100 |
| | 671 | ) |
| | 672 | LANGUAGE plpgsql |
| | 673 | AS $$ |
| | 674 | |
| | 675 | DECLARE |
| | 676 | |
| | 677 | v_record RECORD; |
| | 678 | |
| | 679 | v_confirmed_count INTEGER; |
| | 680 | v_actual_count INTEGER; |
| | 681 | |
| | 682 | v_occupancy_rate NUMERIC; |
| | 683 | |
| | 684 | v_utilization_category VARCHAR; |
| | 685 | |
| | 686 | v_capacity INTEGER; |
| | 687 | |
| | 688 | BEGIN |
| | 689 | |
| | 690 | CREATE TEMP TABLE capacity_utilization_results ( |
| | 691 | venue_id INTEGER, |
| | 692 | venue_name VARCHAR, |
| | 693 | venue_capacity INTEGER, |
| | 694 | wedding_id INTEGER, |
| | 695 | organizer_name VARCHAR, |
| | 696 | wedding_date DATE, |
| | 697 | confirmed_attendees INTEGER, |
| | 698 | actual_attendance INTEGER, |
| | 699 | available_seats INTEGER, |
| | 700 | occupancy_rate_percent NUMERIC, |
| | 701 | utilization_category VARCHAR, |
| | 702 | booking_status VARCHAR, |
| | 703 | booking_date DATE |
| | 704 | ); |
| | 705 | |
| | 706 | FOR v_record IN |
| | 707 | |
| | 708 | SELECT DISTINCT |
| | 709 | v.venue_id, |
| | 710 | v.name, |
| | 711 | v.capacity, |
| | 712 | w.wedding_id, |
| | 713 | u.first_name, |
| | 714 | u.last_name, |
| | 715 | w.date, |
| | 716 | vb.status, |
| | 717 | vb.date |
| | 718 | |
| | 719 | FROM venue v |
| | 720 | |
| | 721 | INNER JOIN venue_booking vb |
| | 722 | ON v.venue_id = vb.venue_id |
| | 723 | |
| | 724 | INNER JOIN wedding w |
| | 725 | ON vb.wedding_id = w.wedding_id |
| | 726 | |
| | 727 | INNER JOIN "user" u |
| | 728 | ON w.user_id = u.user_id |
| | 729 | |
| | 730 | WHERE |
| | 731 | (p_venue_id IS NULL |
| | 732 | OR v.venue_id = p_venue_id) |
| | 733 | |
| | 734 | LOOP |
| | 735 | |
| | 736 | SELECT COUNT(DISTINCT a.guest_id) |
| | 737 | INTO v_confirmed_count |
| | 738 | |
| | 739 | FROM event e |
| | 740 | |
| | 741 | LEFT JOIN attendance a |
| | 742 | ON e.event_id = a.event_id |
| | 743 | AND a.status = 'CONFIRMED' |
| | 744 | |
| | 745 | WHERE e.wedding_id = v_record.wedding_id; |
| | 746 | |
| | 747 | SELECT COUNT(DISTINCT a.guest_id) |
| | 748 | INTO v_actual_count |
| | 749 | |
| | 750 | FROM event e |
| | 751 | |
| | 752 | LEFT JOIN attendance a |
| | 753 | ON e.event_id = a.event_id |
| | 754 | AND a.status = 'ATTENDED' |
| | 755 | |
| | 756 | WHERE e.wedding_id = v_record.wedding_id; |
| | 757 | |
| | 758 | v_confirmed_count := |
| | 759 | COALESCE(v_confirmed_count, 0); |
| | 760 | |
| | 761 | v_actual_count := |
| | 762 | COALESCE(v_actual_count, 0); |
| | 763 | |
| | 764 | v_capacity := v_record.capacity; |
| | 765 | |
| | 766 | IF v_capacity > 0 THEN |
| | 767 | |
| | 768 | v_occupancy_rate := ROUND( |
| | 769 | ( |
| | 770 | CAST(v_confirmed_count AS NUMERIC) |
| | 771 | / v_capacity |
| | 772 | ) * 100, |
| | 773 | 2 |
| | 774 | ); |
| | 775 | |
| | 776 | ELSE |
| | 777 | |
| | 778 | v_occupancy_rate := 0; |
| | 779 | |
| | 780 | END IF; |
| | 781 | |
| | 782 | IF v_confirmed_count > v_capacity THEN |
| | 783 | |
| | 784 | v_utilization_category := 'EXCEEDED'; |
| | 785 | |
| | 786 | ELSIF v_occupancy_rate >= 90 THEN |
| | 787 | |
| | 788 | v_utilization_category := 'HIGH'; |
| | 789 | |
| | 790 | ELSIF v_occupancy_rate >= 60 THEN |
| | 791 | |
| | 792 | v_utilization_category := 'MODERATE'; |
| | 793 | |
| | 794 | ELSE |
| | 795 | |
| | 796 | v_utilization_category := 'LOW'; |
| | 797 | |
| | 798 | END IF; |
| | 799 | |
| | 800 | IF v_occupancy_rate BETWEEN |
| | 801 | p_min_occupancy_percent |
| | 802 | AND p_max_occupancy_percent |
| | 803 | THEN |
| | 804 | |
| | 805 | INSERT INTO capacity_utilization_results |
| | 806 | VALUES ( |
| | 807 | v_record.venue_id, |
| | 808 | v_record.name, |
| | 809 | v_record.capacity, |
| | 810 | v_record.wedding_id, |
| | 811 | v_record.first_name || ' ' || v_record.last_name, |
| | 812 | v_record.date, |
| | 813 | v_confirmed_count, |
| | 814 | v_actual_count, |
| | 815 | v_capacity - v_confirmed_count, |
| | 816 | v_occupancy_rate, |
| | 817 | v_utilization_category, |
| | 818 | v_record.status, |
| | 819 | v_record.date |
| | 820 | ); |
| | 821 | |
| | 822 | END IF; |
| | 823 | |
| | 824 | END LOOP; |
| | 825 | |
| | 826 | RAISE NOTICE |
| | 827 | 'Venue Capacity Utilization Report Generated - % rows processed', |
| | 828 | ( |
| | 829 | SELECT COUNT(*) |
| | 830 | FROM capacity_utilization_results |
| | 831 | ); |
| | 832 | |
| | 833 | END; |
| | 834 | $$; |
| | 835 | }}} |
| | 836 | |
| | 837 | == 2.6 Procedure Characteristics == |
| | 838 | |
| | 839 | * Input Parameters: |
| | 840 | * venue ID |
| | 841 | * minimum occupancy percentage |
| | 842 | * maximum occupancy percentage |
| | 843 | |
| | 844 | * Attendance Analysis: |
| | 845 | * confirmed attendance |
| | 846 | * actual attendance |
| | 847 | |
| | 848 | * Categorization: |
| | 849 | * LOW |
| | 850 | * MODERATE |
| | 851 | * HIGH |
| | 852 | * EXCEEDED |
| | 853 | |
| | 854 | * NULL Safety: |
| | 855 | * COALESCE() handling |
| | 856 | |
| | 857 | * Filtering: |
| | 858 | * occupancy percentage range filtering |
| | 859 | |
| | 860 | == 2.7 Proof of Execution with Sample Data == |
| | 861 | |
| | 862 | === Sample Data Insertion === |
| | 863 | |
| | 864 | {{{ |
| | 865 | #!sql |
| | 866 | INSERT INTO "user" ( |
| | 867 | first_name, |
| | 868 | last_name, |
| | 869 | email, |
| | 870 | phone_number |
| | 871 | ) |
| | 872 | VALUES ( |
| | 873 | 'Александар', |
| | 874 | 'Стојановски', |
| | 875 | 'aleksandar@email.com', |
| | 876 | '070-111-222' |
| | 877 | ); |
| | 878 | |
| | 879 | INSERT INTO wedding ( |
| | 880 | date, |
| | 881 | budget, |
| | 882 | user_id |
| | 883 | ) |
| | 884 | VALUES ( |
| | 885 | '2024-07-20', |
| | 886 | 12000.00, |
| | 887 | 2 |
| | 888 | ); |
| | 889 | |
| | 890 | INSERT INTO venue ( |
| | 891 | name, |
| | 892 | location, |
| | 893 | city, |
| | 894 | address, |
| | 895 | capacity, |
| | 896 | price_per_guest, |
| | 897 | type_id |
| | 898 | ) |
| | 899 | VALUES ( |
| | 900 | 'Golden Palace', |
| | 901 | 'Центар', |
| | 902 | 'Скопје', |
| | 903 | 'Булевар Македонија 15', |
| | 904 | 150, |
| | 905 | 55.00, |
| | 906 | 1 |
| | 907 | ); |
| | 908 | }}} |
| | 909 | |
| | 910 | === Query Execution Result === |
| | 911 | |
| | 912 | {{{ |
| | 913 | venue_id | venue_name | capacity | wedding_id |
| | 914 | ----------+---------------+----------+------------ |
| | 915 | 2 | Golden Palace | 150 | 2 |
| | 916 | }}} |
| | 917 | |
| | 918 | === Calculation Verification === |
| | 919 | |
| | 920 | * Confirmed Attendees: |
| | 921 | * guests with CONFIRMED status |
| | 922 | |
| | 923 | * Actual Attendance: |
| | 924 | * guests with ATTENDED status |
| | 925 | |
| | 926 | * Available Seats: |
| | 927 | * venue capacity minus confirmed attendees |
| | 928 | |
| | 929 | * Occupancy Rate: |
| | 930 | * confirmed attendees percentage relative to venue capacity |
| | 931 | |
| | 932 | * Utilization Category: |
| | 933 | * LOW, MODERATE, HIGH, or EXCEEDED |
| | 934 | |
| | 935 | == Summary == |
| | 936 | |
| | 937 | This scenario demonstrates: |
| | 938 | * venue occupancy analysis |
| | 939 | * attendance tracking |
| | 940 | * utilization categorization |
| | 941 | * operational reporting |
| | 942 | * aggregate SQL calculations |
| | 943 | * stored procedure reporting |