sql >> Databasteknik >  >> RDS >> PostgreSQL

Generera serier av veckointervaller för en given månad

SELECT generate_series(date_trunc('week', date '2013-02-01' + interval '6 days')
                     , date_trunc('week', date '2013-02-01' + interval '1 month - 1 day')
                     , interval '1 week')::date AS day
UNION  SELECT date '2013-02-01'
ORDER  BY 1;

Denna variant behöver inte ett underval, GREATEST eller GROUP BY och genererar bara de rader som krävs. Enklare, snabbare. Det är billigare att UNION en rad.

  • Lägg till 6 dagar till den första dagen i månaden före date_trunc('week', ...) för att beräkna den första måndagen i månaden .

  • Lägg till 1 månad och subtrahera 1 dag före date_trunc('week', ...) för att få den sista måndagen i månaden .
    Detta kan enkelt stoppas i ett enda interval uttryck:'1 month - 1 day'

  • UNION (inte UNION ALL ) den första dagen i månaden för att lägga till den om den inte redan är inkluderad som måndag.

  • Observera att date + interval resulterar i timestamp , vilket är det optimala här. Detaljerad förklaring:

Automatisering

Du kan ange början av datumserien i en CTE:

WITH t(d) AS (SELECT date '2013-02-01')  -- enter 1st of month once
SELECT generate_series(date_trunc('week', d + interval '6 days')
                     , date_trunc('week', d + interval '1 month - 1 day')
                     , interval '1 week')::date AS day
FROM   t
UNION  SELECT d FROM t
ORDER  BY 1;

Eller slå in den i en enkel SQL-funktion för bekvämlighet med upprepade anrop:

CREATE OR REPLACE FUNCTION f_week_starts_this_month(date)
  RETURNS SETOF date AS
$func$
SELECT generate_series(date_trunc('week', $1 + interval '6 days')
                     , date_trunc('week', $1 + interval '1 month - 1 day')
                     , interval '1 week')::date AS day
UNION
SELECT $1
ORDER  BY 1
$func$  LANGUAGE sql IMMUTABLE;

Ring:

SELECT * FROM f_week_starts_this_month('2013-02-01');

Du skulle passera datumet för den första dagen i månaden, men det fungerar för alla datum. Du första dagen och alla måndagar för följande månad.



  1. Anropar pl/sql-funktion med mybatis 3

  2. Yii2 visar data för varje slinga

  3. Körs markörer i Django i den öppna transaktionen?

  4. mysql datumlista med räkning även om ingen data på specifikt datum