sql >> Database teknologi >  >> RDS >> Database

Igen og igen! Håndtering af tilbagevendende hændelser i en datamodel

En tilbagevendende begivenhed er per definition en begivenhed, der gentager sig med et interval; det kaldes også en periodisk begivenhed. Der er mange applikationer, som giver deres brugere mulighed for at konfigurere tilbagevendende begivenheder. Hvordan håndterer et databasesystem tilbagevendende hændelser? I denne artikel vil vi undersøge en måde, hvorpå de håndteres.

Gentagelse er ikke let for ansøgninger at håndtere. Det kan blive en orkanopgave, især når det kommer til at dække alle mulige tilbagevendende scenarier – herunder oprettelse af to-ugentlige eller kvartalsvise begivenheder eller tillade omlægning af alle fremtidige begivenhedstilfælde.

To måder at administrere tilbagevendende begivenheder på

Jeg kan komme i tanke om mindst to måder at håndtere periodiske opgaver i en datamodel. Før vi diskuterer dem, lad os hurtigt gennemgå kravene til denne opgave. I en nøddeskal betyder effektiv ledelse:

  • Brugere har lov til at oprette regelmæssige og tilbagevendende begivenheder.
  • Daglige, ugentlige, to-ugentlige, månedlige, kvartalsvise, to-årige og årlige begivenheder kan oprettes uden begrænsninger for slutdato.
  • Brugere kan omplanlægge eller annullere en forekomst af en begivenhed eller alle fremtidige forekomster af en begivenhed.

I betragtning af disse parametre kommer to måder at håndtere tilbagevendende hændelser på i datamodellen til at tænke på. Vi vil kalde dem den naive måde og den ekspert måde.

Den naive måde: Lagring af alle mulige tilbagevendende forekomster af en begivenhed som separate rækker i en tabel. I denne løsning kræver vi kun én tabel, nemlig event . Denne tabel har kolonner som event_title , start_date , end_date , is_full_day_event osv. start_date og end_date kolonner er tidsstempeldatatyper; på denne måde kan de imødekomme begivenheder, der ikke varer hele dagen.

Fordele: Dette er en ret ligetil tilgang og den enkleste at implementere.

Udemper: Den naive måde har nogle væsentlige ulemper, herunder:

  • Behovet for at gemme alle mulige forekomster af en begivenhed. Hvis du tager hensyn til en stor brugerbase, kræves der en stor del af pladsen. Pladsen er dog ret billig, så dette punkt har ingen større betydning.
  • En meget rodet opdateringsproces. Antag, at en begivenhed er omlagt. I så fald skal nogen opdatere alle forekomster af det. Et stort antal DML-handlinger skal udføres ved omlægning, hvilket har en negativ indvirkning på applikationens ydeevne.
  • Håndtering af undtagelser. Alle undtagelser skal håndteres med ynde, især hvis du skal gå tilbage og redigere den oprindelige aftale efter at have lavet en undtagelse. Antag for eksempel, at du flytter den tredje forekomst af en tilbagevendende begivenhed frem med en dag. Hvad hvis du efterfølgende redigerer tidspunktet for den oprindelige begivenhed? Genindsætter du en anden begivenhed på den oprindelige dag og forlader den, du har fremført? Vil du fjerne linket til undtagelsen? Prøv at ændre det korrekt?
  • The Expert Way: Lagring af et tilbagevendende mønster og generering af tidligere og fremtidige begivenhedstilfælde programmatisk. Denne løsning adresserer ulemperne ved den naive løsning. Vi forklarer ekspertløsningen i detaljer i denne artikel.

    Den foreslåede model




    Oprettelse af begivenheder

    Alle planlagte begivenheder, uanset deres regelmæssige eller tilbagevendende karakter, logges i event bord. Ikke alle begivenheder er tilbagevendende begivenheder, så vi skal bruge en flagkolonne, is_recurring , i denne tabel for eksplicit at angive tilbagevendende hændelser. event_title og event_description kolonner gemmer emnet og en kort oversigt over begivenheder. Begivenhedsbeskrivelser er valgfri, hvorfor denne kolonne er nullbar.

    Som deres navne antyder, er start_date og end_date kolonner gemmer start- og slutdatoerne for begivenheder. I tilfælde af regelmæssige begivenheder gemmer disse kolonner faktiske start- og slutdatoer. Men de gemmer også datoerne for den første og sidste forekomst af periodiske begivenheder. Vi beholder end_date kolonne som nullbar, da brugere kan konfigurere tilbagevendende begivenheder uden slutdato. I dette tilfælde vil fremtidige forekomster op til en hypotetisk slutdato (f.eks. et år) blive vist i brugergrænsefladen.

    is_full_date_event kolonne angiver, om en begivenhed er en heldagsbegivenhed. I tilfælde af en heldagsbegivenhed, start_time og end_time kolonner ville være nul; det er grunden til at holde begge disse kolonner ugyldige.

    created_by og created_date kolonner gemmer, hvilken bruger der har oprettet en begivenhed og datoen, hvor begivenheden blev oprettet.

    Dernæst er der parent_event_id kolonne. Dette spiller en stor rolle i vores datamodel. Jeg vil forklare dens betydning senere.

    Håndtering af gentagelser

    Nu kommer vi direkte til hovedproblemformuleringen:Hvad hvis der oprettes en tilbagevendende begivenhed i event tabel – dvs. den is_recurring flag for begivenheden er "Y"?

    Som forklaret tidligere vil vi gemme et tilbagevendende mønster for begivenheder, så vi kan konstruere alle dets fremtidige begivenheder. Lad os starte med at oprette recurring_pattern bord. Denne tabel har følgende kolonner:

    • Event_id – Denne kolonne er henvist fra event tabel, og den fungerer som den primære nøgle i denne tabel. Det viser det identificerende forhold mellem event og recurring_pattern tabeller. Denne kolonne vil også sikre, at der er maksimalt ét tilbagevendende mønster, der eksisterer for hver begivenhed.
    • Recurring_type_id – Denne kolonne angiver typen af ​​gentagelse, uanset om det er dagligt, ugentligt, månedligt eller årligt.
    • Max_num_of_occurrances – Der er tidspunkter, hvor vi ikke kender den nøjagtige slutdato for en begivenhed, men vi ved, hvor mange begivenheder (møder), der skal til for at gennemføre den. Denne kolonne gemmer et vilkårligt tal, der definerer den logiske ende for en hændelse.
    • Separation_count – Du undrer dig måske over, hvordan en hændelse hver anden uge eller anden gang kan konfigureres, hvis der kun er fire mulige værdier af gentagelsestypen (dagligt, ugentligt, månedligt, årligt). Svaret er separation_count kolonne. Denne kolonne angiver intervallet (i dage, uger eller måneder), før den næste hændelsesinstans er tilladt. For eksempel, hvis en begivenhed skal konfigureres hver anden uge, så separation_count ="1" at opfylde dette krav. Standardværdien for denne kolonne er "0".

    Lad os overveje betydningen af ​​de resterende kolonner i forhold til de forskellige typer af gentagelser.

    Daglig gentagelse

    Har vi virkelig brug for at fange et mønster for en daglig tilbagevendende begivenhed? Nej, fordi alle de detaljer, der kræves for at generere et dagligt gentagelsesmønster, allerede er logget i event tabel.

    Det eneste scenarie, der kræver et mønster, er, når begivenheder er planlagt til alternative dage eller hvert X antal dage. I dette tilfælde er separation_count kolonne vil hjælpe os med at forstå gentagelsesmønsteret og udlede yderligere forekomster.

    Ugentligt gentagelse

    Vi kræver kun én ekstra kolonne, day_of_week , for at gemme, hvilken dag i ugen denne begivenhed finder sted. Hvis det antages, at mandag er den første dag i ugen, og søndag er den sidste, vil mulige værdier være 1,2,3,4,5,6 og 7. Passende ændringer i koden, der genererer individuelle hændelser, bør foretages efter behov. Alle resterende kolonner vil være nul for ugentlige begivenheder.

    Lad os tage en klassisk type ugentlig begivenhed:den to-ugentlige begivenhed. I dette tilfælde vil vi sige, at det sker hver anden uge på en tirsdag, den anden dag i ugen. Så:

    • Det recurring_type_id ville være "ugentlig".
    • separation_count ville være "1".
    • day_of_week ville være "2".

    Månedlig gentagelse

    Udover day_of_week , kræver vi yderligere to kolonner for at opfylde ethvert månedligt gentagelsesscenarie. Kort fortalt er disse kolonner:

    • Week_of_month – Denne kolonne er for begivenheder, der er planlagt til en bestemt uge i måneden – dvs. den første, anden, sidste, næstsidste osv. Vi kan gemme disse værdier som 1,2,3, 4,.. (tæller fra kl. begyndelsen af ​​måneden) eller -1,-2,-3,... (tæller fra slutningen af ​​måneden).
    • Day_of_month – Der er tilfælde, hvor en begivenhed er planlagt på en bestemt dag i måneden, f.eks. den 25. Denne kolonne opfylder dette krav. Ligesom week_of_month , kan den udfyldes med positive tal ( "7" for den 7. dag fra begyndelsen af ​​måneden) eller negative tal ( "-7" for den syvende dag fra slutningen af ​​måneden).

    Lad os nu overveje et mere kompliceret eksempel - en kvartalsvis begivenhed. Antag, at en virksomhed planlægger en kvartalsvis resultatfremskrivningsbegivenhed for de 11 dage i den første måned i hvert kvartal (normalt januar, april, juli og oktober). Så i dette tilfælde:

    • Det recurring_type_id ville være "månedlig".
    • separation_count ville være "2".
    • day_of_month ville være "11".
    • Alle resterende kolonner er null.

    I ovenstående eksempel antager vi, at brugeren opretter den kvartalsvise resultatfremskrivning i januar. Bemærk venligst, at denne adskillelseslogik begynder at tælle fra den måned, uge ​​eller dag, hvor begivenheden oprettes.

    På lignende linjer kan halvårlige hændelser logges som månedlige hændelser med en separation_count af "5".

    Årlig gentagelse

    Årlig gentagelse er ret ligetil. Vi har kolonner for bestemte dage i ugen og måneden, så vi kræver kun én ekstra kolonne for måneden i året. Vi har givet denne kolonne navn til month_of_year .

    Håndtering af undtagelser fra tilbagevendende begivenheder

    Lad os nu komme til undtagelserne. Hvad hvis en bestemt forekomst af en tilbagevendende begivenhed aflyses eller omlægges? Alle sådanne forekomster logges separat i event_instance_exception bord.

    Lad os tage et kig på to kolonner, Is_rescheduled og is_cancelled . Disse kolonner angiver, om denne forekomst er omlagt til en senere dato/tid eller helt annulleret. Hvorfor har jeg to separate kolonner til dette? Tænk bare på begivenheder, der først blev flyttet og senere helt aflyst. Dette sker, og vi har en måde at optage det på med disse kolonner.

    Bortset fra disse to kolonner fungerer alle resterende kolonner på samme måde som i event tabel.

    Hvorfor sammenkæde to begivenheder ved hjælp af parent_event_id ?

    Der er applikationer, som giver brugerne mulighed for at omplanlægge alle fremtidige tilfælde af en tilbagevendende begivenhed. I sådanne tilfælde har vi to muligheder. Vi kan gemme alle fremtidige forekomster i event_instance_exception (tip:ikke en acceptabel løsning). Eller vi kan oprette en ny begivenhed med nye dato/tidsparametre i event tabel og link den til dens tidligere hændelse (den overordnede hændelse) ved hjælp af id_parent_event kolonne.

    Med denne løsning kan vi få alle tidligere forekomster af en begivenhed, selv når dens gentagelsesmønster er blevet ændret.

    Hvordan forbedres håndteringen af ​​tilbagevendende begivenheder?

    Der er nogle mere komplekse områder omkring tilbagevendende begivenheder, som vi ikke har diskuteret. Her er to:

    • Begivenheder, der opstår på helligdage. Når et bestemt tilfælde af en begivenhed indtræffer på en helligdag, skal den så automatisk flyttes til arbejdsdagen umiddelbart efter helligdagen? Eller skal det automatisk annulleres? Under hvilke omstændigheder ville en af ​​disse være gældende?
    • Konflikter mellem begivenheder. Hvad hvis visse begivenheder (der gensidigt udelukker) falder på samme dag?

    Hvilke ændringer skal vi foretage for at indbygge disse kapaciteter? Fortæl os venligst dine synspunkter i kommentarfeltet.


  1. jQuery UI Sorterbar, og skriv derefter rækkefølge i en database

  2. Din ultimative guide til SQL Join:CROSS JOIN – Del 3

  3. MySQL streng udskiftning

  4. MariaDB LAST_INSERT_ID() Forklaret