Классическая задача для финансового сектора на справочник с историей изменений )) Это когда некий объект БД  во внешних ссылках идентифицируется не по 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', перезаполняемая при открытии каждого нового дня ))