Работа с объектами в ракурсе времени

Модератор: Модераторы

Re: Работа с объектами в ракурсе времени

Сообщение Sharfik » 13.01.2025 16:07:35

MaratIsk писал(а):ракурс времени - это не клизма времени? или мозга?! может для начала лучше терминологию реляционных баз освоить?!

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

В интернете десятки предложений с решениями от ИТ компаний, которые от скудностью мышления архитектора и однобоким пониманием задач уже рвотный рефлекс скоро вызывать будут. Там как раз высокие познания реляционных БД показаны, и полное отсутствие понимания что одна и так же информация должна демонстрироваться в разных ракурсах/точках зрения. Кому то нужно по времени исполнительных ресурсов разложить, кому то по договорам, кому то по деньгам. С деньгами вообще ноль полный предложений.
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 801
Зарегистрирован: 20.07.2013 01:04:30

Re: Работа с объектами в ракурсе времени

Сообщение debi12345 » 15.01.2025 12:00:56

Классическая задача для финансового сектора на справочник с историей изменений )) Это когда некий объект БД во внешних ссылках идентифицируется не по ID(номеру строки) текущей записи в справочнике, а по коду, один раз присвоенному при создании этого объекта.

Код: Выделить всё
table 'Staff' -> id / code / fio / date_activ / date_deactiv
--------------------------------------------
1 1       Pupkin 01.01.2024 01.05.2024
2 1       Pupkin 01.05.2024 01.01.2025
3 1       Pupkin 01.01.2025 null    -> текущая активная запись


Код: Выделить всё
table 'Salary' -> id / code / staff_code / salary /date_activ / date_deactiv
staff_code -> ссылка на 'Staff.code'
--------------------------------------------
1 1       1 1000.00 01.01.2024 01.05.2025
2 1       1 100000.00 01.05.2025 null    -> текущая активная запись

В таком случае данные из участвующих в запросах таблиц нужно отбирать по условию 'date_activ <= <some_date> and (date_deаctiv is null or date_deactiv > <some_date>)', в случае нескольких удовлетворяющих записей выбрать среди них запись с последней (по дате) 'date_activ'. Это может показаться громоздким в случае много-табличных запросов, но все становится просто, если БД поддерживает VIEWшки, а еще лучше (наприклад PostgreSQL) - функции, принимающие аргументы (например <some_date>) и возвращающие VIEWшки ))

Код: Выделить всё
CREATE TABLE ref_suppl_index (
        id SERIAL4 NOT NULL,
        code INTEGER NOT NULL,
        name INTEGER NOT NULL, /*индекс*/
        company_code INTEGER NOT NULL,
        catalog_code INTEGER NOT NULL,
        indexes_ss INTEGER[],
        indexes_retail INTEGER[],
        date_input DATE,
        date_activ DATE,
        date_deactiv DATE,
        oper_code INTEGER,
        rec_state INTEGER
);

CREATE UNIQUE INDEX ref_suppl_index_pkey ON ref_suppl_index (id);
CREATE UNIQUE INDEX ref_suppl_index_code_uidx ON ref_suppl_index (code,date_activ) WHERE date_deactiv IS NULL OR date_deactiv > date_deactiv;
CREATE UNIQUE INDEX ref_suppl_index_name_uidx ON ref_suppl_index (company_code,catalog_code,name) WHERE date_deactiv IS NULL OR date_deactiv > date_deactiv;
CREATE INDEX ref_suppl_index_da_idx ON ref_suppl_index (date_activ);
CREATE INDEX ref_suppl_index_dda_idx ON ref_suppl_index (date_deactiv);

CREATE OR REPLACE VIEW "v_suppl_index" AS SELECT
        id,
        code,
        name, /*индекс*/
        company_code,
        catalog_code,
        indexes_ss,
        indexes_retail
FROM ref_suppl_index;
----------------------------
CREATE OR REPLACE FUNCTION "f_suppl_index"(date_activ date) RETURNS SETOF "int4" AS $BODY$
select
        max(a.id)
from
        ref_suppl_index a
inner join (
select
        max(date_activ) as date_activ,
        code
from
        ref_suppl_index
where
  ($1 >= date_activ)
and
  (($1 < date_deactiv) or date_deactiv is null)
group by code
) b
using
        (code,date_activ)
group by
        a.code;
$BODY$ LANGUAGE 'sql' VOLATILE COST 100 ROWS 1000;
----------------------
CREATE OR REPLACE FUNCTION "fv_suppl_index"(date_activ date) RETURNS SETOF "v_suppl_index" AS $BODY$
select
        id,
        code,
        name, /*индекс*/
        company_code,
        catalog_code,
        indexes_ss,
        indexes_retail
from
        ref_suppl_index a1 inner join f_suppl_index($1) a2 on a1.id=a2
$BODY$ LANGUAGE 'sql' VOLATILE COST 100 ROWS 1000;


Использование в запросах - например данные, актуальные на дату 2024-11-03 :
Код: Выделить всё
SELECT si.code AS si_code, si.name FROM fv_suppl_index('2024-11-03'::date) si;

Для упрощения статистических выборок рекомендуется ( и плевать на строгую реляционность ! ) копировать используемые в статистике данные из справочников в рабочие таблицы при вставке в них - чтобы позже не нужно было обращаться к справочникам ))

Если БД не поддерживает такие VIEWшки, то приходится городить дурацкий огород с открытием/закрытием рабочего дня - там для кажого справочника согласно анализа "date_activ" и "date_deactiv" создается дополнительная таблица маппинга "code ->id', перезаполняемая при открытии каждого нового дня ))
Последний раз редактировалось debi12345 16.01.2025 22:07:49, всего редактировалось 1 раз.
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Re: Работа с объектами в ракурсе времени

Сообщение Sharfik » 16.01.2025 02:52:55

Интересно, интересно. Будем посмотреть) Спасибо.
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 801
Зарегистрирован: 20.07.2013 01:04:30

Пред.

Вернуться в Общие вопросы

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2

Рейтинг@Mail.ru