SQL (ANSI)ProgrammatieSQL Developer

Bereken het piek aantal gelijktijdig actieve reserveringen binnen een hotelboekingssysteem gegeven incheck- en uitchecktijdstempels, met gebruik van strikt ANSI SQL set-gebaseerde operaties zonder gebruik te maken van tijdslicing of procedurele lussen?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord op de vraag

Geschiedenis van de vraag: Tijdelijke intervalanalyse heeft relationele databases sinds de jaren 70 uitgedaagd, aangezien SQL oorspronkelijk is ontworpen zonder native intervaltypen. Vroege oplossingen vertrouwden op cursor-gebaseerde iteratie of cartesiaanse producten tussen intervallen, wat resulteerde in kwadratische complexiteit. De introductie van venstervariabelen in SQL:2003 en de specificatie ROWS BETWEEN voor frames stelde efficiënte continuïteitaggregaten in staat, waarmee de basis voor moderne op gebeurtenissen gebaseerde gelijktijdigheidsberekeningen werd gelegd.

Het probleem: Het bepalen van de maximale gelijktijdigheid vereist inzicht in de precieze momenten waarop statuswijzigingen optreden—specifiek wanneer een reservering begint of eindigt. De naïeve benadering breidt elk interval uit tot discrete tijdseenheden (tijd-slicing), wat computationeel onwerkbaar is voor langdurige verblijven. De kernuitdaging ligt in het berekenen van hoeveel intervallen op enig specifiek moment overlappen zonder elk moment van de tijdlijn te materialiseren.

De oplossing: Pas een discrete gebeurtenissimulatiepatroon toe. Transformeer de intervaltabel in een gebeurtenisstroom met behulp van UNION ALL, waarbij een gewicht van +1 wordt toegekend aan elke incheck (begin) en -1 aan elke uitcheck (eind). Door deze evenementen chronologisch te sorteren en een lopende som toe te passen via SUM() OVER (ORDER BY ...) venstervariabelen, bepaal je de actieve telling op elk overgangspunt. De maximale waarde van deze lopende som vertegenwoordigt de piekconcurrentie.

WITH events AS ( SELECT check_in AS event_time, 1 AS delta FROM reservations UNION ALL SELECT check_out AS event_time, -1 AS delta FROM reservations ), concurrency AS ( SELECT event_time, SUM(delta) OVER ( ORDER BY event_time, delta DESC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS active_count FROM events ) SELECT MAX(active_count) AS peak_concurrency FROM concurrency;

Situatie uit het leven

Probleembeschrijving: Een luxe resortketen ervoer mysterieuze overboekingen tijdens feestdagen, ondanks dat hun beschikbaarheidssysteem vacatures rapporteerde. De legacy-query berekende de dagelijkse bezetting door elke reservering te splitsen in afzonderlijke nachtelijke rijen via een recursieve CTE, wat miljoenen rijen genereerde voor verblijven van een maand. Tijdens de analyse van oudejaarsavond vereiste deze aanpak 12 seconden om uit te voeren en maakte de boekingstransactietabel vast, waardoor realtime reserveringen werden verhindert.

Oplossing A: Tijd-slice expansie met tel-tabels. Het operationele team stelde aanvankelijk voor om een kalendertabel vooraf te genereren en deze tegen reserveringen te koppelen met behulp van event_date BETWEEN check_in AND check_out. Deze methode biedt intuïtieve dagelijkse totalen die compatibel zijn met standaard GROUP BY clausules. Voordelen: Conceptueel eenvoudig voor zakelijke analisten, gemakkelijk te integreren met bestaande BI-tools. Nadelen: Genereert O(N × D) rijen waar D de gemiddelde duur is, wat leidt tot exponentiële groei; faalt catastrofaal bij minutengarbage of langlopende huurcontracten; verbruikt overmatige tempdb-ruimte.

Oplossing B: Intervalboom met gematerialiseerde paden. Een senior architect stelde voor een segmentboomstructuur te implementeren met geneste sets om intervalgrenzen te indexeren, wat logaritmische overlapquery's mogelijk maakt. Voordelen: Optimale theoretische complexiteit voor frequente updates en puntquery's. Nadelen: Vereist complexe triggers om de boom in evenwicht te houden; schendt ANSI SQL-portabiliteit door te vertrouwen op procedurele extensies; introduceert schrijfversterking die de OLTP-werkbelasting schaadt tijdens boekingspieken.

Oplossing C: Chronologische gebeurtenisstroom met lopende sommen (gekozen). Het database-team nam de op gebeurtenissen gebaseerde aanpak aan, waarbij elke reserveringsgrens als een delta-operatie werd behandeld. Dit verminderde de dataset van miljoenen explosieve rijen tot exact 2N evenementen (start en einde voor elke reservering). Voordelen: O(N log N) complexiteit, gedomineerd door de sorteeroperatie, constante geheugengebruik, en pure ANSI SQL compatibiliteit op PostgreSQL, Oracle en SQL Server. Nadelen: Vereist zorgvuldige omgang met gelijktijdige evenementen en identificeert niet inherent welke specifieke reserveringen bijdroegen aan de piek zonder extra joins.

Resultaat: Query-latentie daalde van 12 seconden naar 45 milliseconden. De analyse onthulde dat de werkelijke bottleneck niet het kamerinventaris (500 eenheden) was, maar de capaciteit van de lift, aangezien 320 gasten probeerden gelijktijdig in te checken om 18:00 uur. Dit inzicht leidde tot de implementatie van gestaggerde incheckniveaus in plaats van de bouw van een nieuwe vleugel, wat $2M aan kapitaalinvesteringen bespaarde en vastlopers elimineerde.

Wat kandidaten vaak missen

Waarom vereist de oplossing specifiek ORDER BY event_time, delta DESC, en wat gebeurt er als je de secundaire sortering op delta weglaat?

Kandidaten negeren vaak de semantiek van grensgevallen bij gedeelde tijdstempels. Wanneer de ene gast precies om 10:00 uur uitcheckt en een andere gast om 10:00 uur incheckt, bepaalt de verwerkingsvolgorde of de kamer gelijktijdig door twee gasten lijkt bezet. Door te sorteren met delta DESC zorgen we ervoor dat -1 (vertrek) vóór +1 (aankomst) wordt verwerkt bij identieke tijdstempels. Zonder deze secundaire sortering daalt de lopende som tijdelijk en springt vervolgens, waardoor mogelijk een valse piek wordt geregistreerd wanneer de vorige staat eigenlijk hoger was. Deze subtiele ordening voorkomt off-by-one fouten die kunnen leiden tot overboekingskwetsbaarheden in productiesystemen.

Hoe zou je deze query aanpassen om te identificeren welke specifieke reserveringen actief waren tijdens het piekconcurrentiemoment, niet slechts de telling?

De meeste kandidaten proberen binnen dezelfde CTE te filteren, en beseffen niet dat de piek een continu interval kan bestrijken in plaats van een enkel punt. De robuuste aanpak vereist een tweeërlei strategie: isoleren eerst de tijdstempel waarop active_count gelijk is aan het maximum met behulp van een subquery of CTE, en vervolgens terugkoppelen naar de oorspronkelijke reserveringstabel met behulp van de overlapvoorwaarde r.check_in <= peak.event_time AND r.check_out > peak.event_time. Kandidaten missen dat meerdere tijdstempels dezelfde maximale waarde kunnen delen, die een DISTINCT of EXISTS clausule vereisen om dubbele reserveringslijsten te voorkomen wanneer de piekpunt aanhoudt over verschillende gebeurtenistransities.

Welke wijzigingen zijn noodzakelijk als de bedrijfsregels veranderen zodat de uitchecktijd inclusief is (gast bezet de kamer tot 23:59 uur) in plaats van exclusief, en hoe beïnvloedt dit de evenementgewicht?

Kandidaten over het hoofd zien vaak de semantiek van intervalgrenzen. Inclusieve eindpunten [start, end] creëren overlappingen wanneer de ene reservering eindigt en een andere begint op dezelfde dag. De oplossing vereist dat inclusieve grenzen worden omgezet in exclusieve door een infinitesimale epsilon (of de volgende discrete tijdseenheid) toe te voegen aan uitchecktijden voordat de -1 gebeurtenis wordt gegenereerd. Alternatief, pas de joinlogica aan om check_out >= event_time te gebruiken terwijl de lopende som logica intact blijft. Het nalaten van deze aanpassing transformeert het discrete gebeurtenismodel van half-open naar gesloten intervallen, waardoor de algoritme-conflicten rapporteert waar geen zijn en de werkelijke capaciteit met precies één eenheid tijdens perioden van hoge omlooptijd onderschat.