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

Hvad er MySQL-alternativet til Oracles NEXT_DAY-funktion?

Jeg vil kaste min hat i ringen med endnu en tilgang:

Rediger: Jeg indser noget forsinket, at den pågældende Oracle-funktion tager en streng som det andet argument, og derfor passer dette ikke præcist til kravet. Men MySQL har allerede venligt defineret 0 - 6 som mandag - søndag, og alligevel har jeg moralske indvendinger mod at bruge en streng som argument for denne type ting. En streng ville enten komme fra brugerinput eller endnu en kortlægning i kode på højere niveau mellem numeriske og strengværdier. Hvorfor ikke videregive et heltal? :)

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

For at opdele den del, der bestemmer INTERVAL værdi:

Den første del af ligningen får simpelthen forskydningen mellem den angivne ugedag og ugedagen på den angivne dato:

p_weekday - WEEKDAY(p_date)

Dette vil returnere et positivt tal, hvis p_weekday er større end WEEKDAY(p_date) og omvendt. Nul vil blive returneret, hvis de er de samme.

ROUND() segment bruges til at bestemme, om den ønskede ugedag (p_weekday ) er allerede fundet sted i den aktuelle uge i forhold til datoen (p_date ) angivet. Så for eksempel...

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

..returnerer 0 , hvilket angiver den søndag (6 ) har ikke fundet sted i denne uge, som 2019-01-25 er en fredag. Ligeledes...

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

... returnerer 1 fordi onsdag (2 ) er allerede bestået. Bemærk, at dette vil returnere 0 hvis p_weekday er den samme som ugedagen p_date .

Denne værdi (enten 1 eller 0 ) ganges derefter med konstanten 7 (antal dage i en uge).

Derfor hvis p_weekday allerede har fundet sted i den aktuelle uge, vil det tilføje 7 til offset p_weekday - WEEKDAY(p_date) , fordi den forskydning ville være et negativt tal, og vi ønsker en dato i fremtiden.

Hvis p_weekday endnu ikke har fundet sted i den aktuelle uge, så kan vi bare tilføje forskydningen til den aktuelle dato, fordi forskydningen vil være et positivt tal. Derfor afsnittet ROUND(...) * 7 er lig med nul og i det væsentlige ignoreret.

Mit ønske med denne tilgang var at simulere en IF() tilstand matematisk. Dette ville være lige så gyldigt:

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

Og af hensyn til objektiviteten er IF ved at køre 1M iterationer et par gange af hver funktion. -baseret version var i gennemsnit omkring 4,2 % hurtigere end ROUND -baseret version.



  1. Ikke i stand til at generere et Google-diagram ved hjælp af MySQL-tabeldata som datakilde

  2. Hvordan indsætter man flere poster og får identitetsværdien?

  3. MySQL + Query for at returnere alle rækker, der har kolonner, der er 'aktive' i en anden tabel

  4. Push-meddelelse fra enhed til enhed over lokalt netværk UDEN C2DM