sql >> Database >  >> RDS >> Oracle

Wat is het MySQL-alternatief voor de NEXT_DAY-functie van Oracle?

Ik ga mijn hoed in de ring gooien met nog een andere benadering:

Bewerken: Ik realiseer me enigszins laat dat de Oracle-functie in kwestie een string als het tweede argument heeft, en dus voldoet dit niet precies aan de vereiste. MySQL heeft echter al vriendelijk 0 - 6 gedefinieerd als maandag - zondag, en hoe dan ook, ik heb morele bezwaren tegen het gebruik van een string als argument voor dit soort dingen. Een tekenreeks zou ofwel afkomstig zijn van gebruikersinvoer of nog een andere toewijzing in code op een hoger niveau tussen numerieke en tekenreekswaarden. Waarom geef je geen geheel getal door? :)

CREATE FUNCTION `fnDayOfWeekGetNext`(
        p_date DATE,
        p_weekday TINYINT(3)
        ) RETURNS date
BEGIN

        RETURN DATE_ADD(p_date, INTERVAL p_weekday - WEEKDAY(p_date) + (ROUND(WEEKDAY(p_date) / (p_weekday + WEEKDAY(p_date) + 1)) * 7) DAY);

END

Om het gedeelte op te splitsen dat de INTERVAL bepaalt waarde:

Het eerste deel van de vergelijking geeft gewoon de afwijking tussen de opgegeven weekdag en de weekdag van de opgegeven datum:

p_weekday - WEEKDAY(p_date)

Dit levert een positief getal op als p_weekday is groter dan WEEKDAY(p_date) en vice versa. Nul wordt geretourneerd als ze hetzelfde zijn.

De ROUND() segment wordt gebruikt om te bepalen of de gevraagde dag van de week (p_weekday ) heeft al plaatsgevonden in de huidige week ten opzichte van de datum (p_date ) opgegeven. Dus, bijvoorbeeld...

ROUND(WEEKDAY('2019-01-25') / (6 + WEEKDAY('2019-01-25') + 1))

..retourneert 0 , wat aangeeft dat zondag (6 ) heeft deze week niet plaatsgevonden, zoals 2019-01-25 is een vrijdag. Zo ook...

ROUND(WEEKDAY('2019-01-25') / (2 + WEEKDAY('2019-01-25') + 1))

...retourneert 1 omdat woensdag (2 ) is al voorbij. Merk op dat dit 0 zal opleveren if p_weekday is hetzelfde als de weekdag van p_date .

Deze waarde (ofwel 1 of 0 ) wordt vervolgens vermenigvuldigd met de constante 7 (het aantal dagen in een week).

Dus als p_weekday al heeft plaatsgevonden in de huidige week, wordt 7 toegevoegd aan de offset p_weekday - WEEKDAY(p_date) , omdat die offset een negatief getal zou zijn en we willen een datum in de toekomst.

Als p_weekday nog moet plaatsvinden in de huidige week, dan kunnen we de offset gewoon optellen bij de huidige datum omdat de offset een positief getal zal zijn. Vandaar de sectie ROUND(...) * 7 is gelijk aan nul en wordt in wezen genegeerd.

Mijn wens voor deze aanpak was het simuleren van een IF() voorwaarde wiskundig. Dit zou even geldig zijn:

RETURN DATE_ADD(p_date, INTERVAL p_weekday - WEEKDAY(p_date) + IF(p_weekday - WEEKDAY(p_date) < 0, 7, 0) DAY);

En in het belang van de objectiviteit, bij het uitvoeren van 1M iteraties een paar keer van elke functie de IF -gebaseerde versie gemiddeld ongeveer 4,2% sneller dan de ROUND -gebaseerde versie.



  1. MYSQL-query WHERE IN vs OR

  2. Verbinding met MySQL na een tijdje verbroken en geen verbinding meer gemaakt

  3. Kolomwaarden samenvoegen tot een door komma's gescheiden lijst

  4. in postgresql, zijn partities of meerdere databases efficiënter?