Выбор определенных столбцов из таблицы с датами в качестве столбцов - PullRequest
1 голос
/ 09 мая 2020

У меня есть таблица, в которой имена столбцов похожи на годы "2020-05","2020-06", "2020-07" et c и столько лет как столбцы. Мне нужно выбрать только столбцы текущего месяца, следующего месяца и третьего месяца из этой таблицы. (DB : PostgreSQL Version 11)

Но поскольку имена столбцов «ТЕКСТ» имеют формат YYYY-MM, как я могу выбрать только текущий месяц и будущие 2 месяца из этой таблицы без жесткого кодирования имен столбцов.

Ниже представлена ​​структура таблицы, имя: static_data enter image description here

Требуемый оператор выбора выглядит следующим образом. Таблица содержит данные за 14 месяцев, как показано выше. снимок экрана, например ДАТЫ в виде столбцов. Из этого я хочу, чтобы столбцы текущего месяца и следующих 2 месяцев вместе с их данными, что-то вроде ниже.

ВЫБРАТЬ «2020-05», «2020-06», «2020 -07 "из статического - ВЫБРАТЬ Текущий месяц и следующие 2 месяца Требуемый вывод:

enter image description here

Ответы [ 3 ]

2 голосов
/ 10 мая 2020

Практически невозможно получить фактическое значение текущего месяца в качестве имени столбца, но вы можете сделать что-то вроде этого:

select d.item_sku,
       d.status,
       to_jsonb(d) ->> to_char(current_date, 'yyyy-mm') as current_month,
       to_jsonb(d) ->> to_char(current_date + interval '1 month', 'yyyy-mm') as "month + 1",
       to_jsonb(d) ->> to_char(current_date + interval '2 month', 'yyyy-mm') as "month + 2"
from bad_design d
;
0 голосов
/ 09 мая 2020

Заявление об ограничении ответственности: это не отвечает на ваш вопрос, но это слишком длинный для комментария.

Вам необходимо исправить дизайн этой таблицы. Вместо того, чтобы хранить даты в столбцах, вы должны размещать каждую дату в отдельной строке .

У вашего текущего дизайна есть множество недостатков:

  • очень простые запросы чрезвычайно сложны: фильтрация по датам, агрегирование ... Все эти операции требуют динамического c SQL, что значительно усложняет

  • добавление или удаление новых date требует изменения структуры таблицы

  • хранилище тратится впустую для строк, в которых заполнены не все столбцы

Вместо этого рассмотрите этот простой дизайн, с одной таблицей, в которой хранятся основные данные каждого item_sku, и дочерней таблицей

create table myskus (
    item_sku int primary key,
    name text,
    cat_level_3_name text
);

create table myvalues (
    item_sku int references myskus(item_sku),
    date_sku date,
    value_sku text,
    primary key (item_sku, date_sku)
);

Теперь ваш исходный вопрос легко решить:

select v.*, s.name, s.cat_level_3_name
from myskus s
inner join myvalues v on v.item_sku = s.item_sku
where 
    v.date_sku >= date_trunc('month', now()) 
    and v.date_sku < date_trunc('month', now()) + interval '3 month'
0 голосов
/ 09 мая 2020

Технически для этого можно использовать информационную схему. Но, как сказал GMB , пожалуйста, переделайте свою схему и не подходите к этой проблеме таким образом, в первую очередь.

Специальная схема information_schema содержит метаданные о вашей БД. Среди них - сведения о существующих столбцах . Другими словами, вы можете запросить его и преобразовать их имена в даты, чтобы сравнить их с тем, что вам нужно.
Вот несколько советов.

Запросить существующие имена столбцов.

SELECT column_name
FROM information_schema.columns
WHERE table_schema = 'your_schema'
  AND table_name   = 'your_table'

Сравните две даты.

SELECT now() + INTERVAL '3 months' < now() AS compare;
 compare                                                       
---------
 f
(1 row)

Вы уже довольно близко подошли к преобразованию.

Получайте удовольствие и переделайте свою схему!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...