PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Gerar séries de intervalos de semanas para determinado mês

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;

Esta variante não precisa de uma subseleção, GREATEST ou GROUP BY e gera apenas as linhas necessárias. Mais simples, mais rápido. É mais barato usar UNION uma linha.

  • Adicione 6 dias ao primeiro dia do mês antes de date_trunc('week', ...) para calcular a primeira segunda-feira do mês .

  • Adicione 1 mês e subtraia 1 dia antes de date_trunc('week', ...) para obter a última segunda-feira do mês .
    Isso pode ser convenientemente colocado em um único interval expressão:'1 month - 1 day'

  • UNION (não UNION ALL ) no primeiro dia do mês para adicioná-lo, a menos que já esteja incluído como segunda-feira.

  • Observe que date + interval resulta em timestamp , que é o ideal aqui. Explicação detalhada:

Automação


Você pode fornecer o início da série de datas em um 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;

Ou envolva-o em uma função SQL simples por conveniência com chamadas repetidas:
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;

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

Você passaria a data para o primeiro dia do mês, mas funciona para qualquer encontro. Você no primeiro dia e todas as segundas-feiras do mês seguinte.