sql >> Databasteknik >  >> RDS >> Oracle

Vad är MySQL-alternativet till Oracles NEXT_DAY-funktion?

Jag ska kasta min hatt i ringen med ännu ett tillvägagångssätt:

Redigera: Jag inser något försenat att Oracle-funktionen i fråga tar en sträng som det andra argumentet, så detta passar inte exakt kravet. Men MySQL har redan vänligt definierat 0 - 6 som måndag - söndag, och hur som helst har jag moraliska invändningar mot att använda en sträng som argument för den här typen av saker. En sträng kommer antingen från användarinmatning eller ännu en mappning i kod på högre nivå mellan numeriska och strängvärden. Varför inte passera ett 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

För att dela upp delen som bestämmer INTERVAL värde:

Den första delen av ekvationen får helt enkelt offset mellan den angivna veckodagen och veckodagen för det angivna datumet:

p_weekday - WEEKDAY(p_date)

Detta returnerar ett positivt tal om p_weekday är större än WEEKDAY(p_date) och vice versa. Noll kommer att returneras om de är likadana.

ROUND() segment används för att avgöra om den begärda veckodagen (p_weekday ) har redan inträffat under den aktuella veckan i förhållande till datumet (p_date ) specificerad. Så, till exempel...

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

..returerar 0 , vilket indikerar den söndagen (6 ) har inte inträffat den här veckan, eftersom 2019-01-25 är en fredag. Likaså...

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

...returerar 1 eftersom onsdag (2 ) har redan gått. Observera att detta returnerar 0 om p_weekday är samma som veckodagen p_date .

Detta värde (antingen 1 eller 0 ) multipliceras sedan med konstanten 7 (antal dagar i en vecka).

Därför om p_weekday redan har inträffat under den aktuella veckan kommer det att lägga till 7 till offset p_weekday - WEEKDAY(p_date) , eftersom den offset skulle vara ett negativt tal och vi vill ha ett datum i framtiden.

Om p_weekday har ännu inte inträffat under den aktuella veckan, så kan vi bara lägga till offset till det aktuella datumet eftersom offset kommer att vara ett positivt tal. Därav avsnittet ROUND(...) * 7 är lika med noll och ignoreras i huvudsak.

Min önskan med detta tillvägagångssätt var att simulera en IF() tillstånd matematiskt. Detta skulle vara lika giltigt:

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

Och i objektivitetens intresse, när du kör 1 miljon iterationer några gånger av varje funktion, visas IF -baserad version var i genomsnitt cirka 4,2 % snabbare än ROUND -baserad version.



  1. Entity Framework - Linq-fråga med ordning efter och grupp efter

  2. Hur man kombinerar IN-operatör med LIKE-skick (eller bästa sättet att få jämförbara resultat)

  3. Openshift:Hur fjärråtkomst till MySQL?

  4. SQL SELECT allt efter ett visst tecken