создать таблицу с датами — sql

#sql #amazon-redshift

#sql #amazon-redshift

Вопрос:

У меня есть запрос, который может создать таблицу с датами, как показано ниже:

 with digit as (
select 0 as d union all 
select 1 union all select 2 union all select 3 union all
select 4 union all select 5 union all select 6 union all
select 7 union all select 8 union all select 9        
),

seq as (
select a.d   (10 * b.d)   (100 * c.d)   (1000 * d.d) as num
from digit a
    cross join
    digit b
    cross join
    digit c
    cross join
    digit d
order by 1        
)

select (last_day(sysdate)::date - seq.num)::date as "Date"
from seq;
 

Как это можно изменить, чтобы генерировать только даты

Спасибо

Ответ №1:

демонстрация: db<>скрипка

 WITH dates AS (
    SELECT 
        date_trunc('month', CURRENT_DATE) AS first_day_of_month,
        date_trunc('month', CURRENT_DATE)   interval '1 month -1 day' AS last_day_of_month   
)
SELECT
    generate_series(first_day_of_month, last_day_of_month, interval '1 day')::date
FROM dates
 
  • date_trunc() усекает тип date (или timestamp ) до определенной части даты. date_trunc('month', ...) удаляет все части, кроме year и month . Для всех остальных частей устанавливаются минимально возможные значения. Итак, day для части установлено значение 1 . Вот почему вы получаете первый день месяца с этим.
  • добавление месяца возвращает первое число следующего месяца, вычитая из этого день, получается последний день текущего месяца.
  • Наконец, вы можете сгенерировать ряд дат с начальной и конечной датой, используя generate_series() функцию

Редактировать: Redshift не поддерживает generate_series() with type date и timestamp , но with integer . Итак, вместо этого нам нужно создать integer серию и добавить результаты к первому числу месяца:

db<>скрипка

 WITH dates AS (
    SELECT 
        date_trunc('month', CURRENT_DATE) AS first_day_of_month,
        date_trunc('month', CURRENT_DATE)   interval '1 month -1 day' AS last_day_of_month   
)
SELECT
    first_day_of_month::date   gs
FROM 
    dates,
    generate_series(
        date_part('day', first_day_of_month)::int - 1, 
        date_part('day', last_day_of_month)::int - 1
    ) as gs
 

Комментарии:

1. @Adella добавил версию, совместимую с Redshift

2. Фух, на самом деле у меня нет экземпляра Redshift для тестирования… Может быть, это работает? dbfiddle.uk /… или это dbfiddle.uk /…

3. Это не работает? dbfiddle.uk /…

4. @Adella: В документах из Redshift говорится, что это должно сработать, если ВЫБОР заключен в параграфы: docs.aws.amazon.com/en_us/redshift/latest/dg/… Итак, может быть, это? dbfiddle.uk /…

5. Сделано @S-Man! Спасибо!!

Ответ №2:

Это отвечает на исходную версию вопроса.

Вы бы использовали generate_series() :

 select gs.dte
from generate_series(date_trunc('month', now()::date),
                     date_trunc('month', now()::date)   interval '1 month' - interval '1 day',
                     interval '1 day'
                    ) gs(dte);
 

Вот скрипка db<> .

Комментарии:

1. Generate_series () является функцией только ведущего узла в Redshift и не может использоваться для хранения данных в таблице. Это даст правильный результат, но поскольку запрос был направлен на способ создания таблицы, это не удовлетворит потребности.

2. @BillWeiner . , , Вопрос был помечен как Postgres — и только Postgres — когда я ответил на него.