Вот основная таблица с данными:
CREATE TABLE my_report
(
id serial NOT NULL primary key,
report_timestamp timestamp without time zone NOT NULL,
value_id integer NOT NULL,
text_value character varying(255),
numeric_value double precision,
bool_value boolean,
dt_value timestamp with time zone,
CONSTRAINT my_report_fkey_valdef FOREIGN KEY (value_id)
REFERENCES public.my_value_defs (value_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE RESTRICT
);
Содержит несколько столбцов для каждого значения, поскольку значения могут быть разных типов данных.
Какой столбец будет взят, зависит от 'столбец data_type 'второй таблицы, связанный с value_id
внешним ключом:
CREATE TABLE my_value_defs
(
value_id serial NOT NULL primary key,
value_name character varying(50) NOT NULL,
data_type integer NOT NULL,
CONSTRAINT my_value_defs_pkey PRIMARY KEY (value_id),
CONSTRAINT my_value_defs_value_name_key UNIQUE (value_name)
);
Теперь я пытаюсь сократить огромный запрос SQL, создав функцию, которая может возвращать либо text_value
, либо numeric_value
, либо bool_value
или dt_value
, но обнаружил, что я должен явно определить возвращаемый тип данных:
CREATE OR REPLACE FUNCTION public.rep_dta_val(
val_id integer,
dt timestamp with time zone,
timeout integer)
RETURNS timestamp with time zone AS -- ********** HERE **********
$BODY$SELECT
r.dt_value
FROM
my_report r
WHERE
r.value_id = val_id
AND r.report_timestamp BETWEEN
dt - make_interval(secs := timeout)
AND dt
ORDER BY
r.report_timestamp desc
LIMIT 1;$BODY$
LANGUAGE sql VOLATILE
COST 100;
Эта функция еще не завершена, поэтому, пожалуйста, не жалуйтесь об этом здесь.
Iне люблю конвертировать все в текст.Типы данных должны быть сохранены.
Когда невозможно создать функцию с переменным типом выходных данных, тогда я должен сгенерировать полный SQL-запрос полной длины в моем приложении, например:
SELECT
(SELECT r.text_value as acc_right FROM my_report r WHERE r.value_id = 3 AND r.report_timestamp BETWEEN now() - INTERVAL '60 seconds' AND now() ORDER BY r.report_timestamp desc LIMIT 1),
(SELECT r.numeric_value as h_angle FROM my_report r WHERE r.value_id = 4 AND r.report_timestamp BETWEEN now() - INTERVAL '60 seconds' AND now() ORDER BY r.report_timestamp desc LIMIT 1),
(SELECT r.text_value as vol_flow FROM my_report r WHERE r.value_id = 25 AND r.report_timestamp BETWEEN now() - INTERVAL '60 seconds' AND now() ORDER BY r.report_timestamp desc LIMIT 1),
(SELECT r.numeric_value as draft_mid FROM my_report r WHERE r.value_id = 57 AND r.report_timestamp BETWEEN now() - INTERVAL '60 seconds' AND now() ORDER BY r.report_timestamp desc LIMIT 1),
(SELECT r.dt_value as eta_timestamp FROM my_report r WHERE r.value_id = 58 AND r.report_timestamp BETWEEN now() - INTERVAL '60 seconds' AND now() ORDER BY r.report_timestamp desc LIMIT 1);
Вышеупомянутый запрос делает именно то, что мне нужно, но он слишком длинный, поэтому я создал несколько функций, по одной для каждого типа данных, и использую их следующим образом:
SELECT
rep_txt_val( 3, now(), 60) as acc_right,
rep_num_val( 4, now(), 60) as h_angle,
rep_txt_val(25, now(), 60) as vol_flow,
rep_num_val(57, now(), 60) as draft_mid,
rep_dta_val(58, now(), 60) as eta_timestamp;
Теперь я хотел быиметь универсальную функцию для всех типов данных.
PS Зачем использовать EAV ?
Потому что раньше это была обычная таблица, а ЭТО было кошмаромпотому что столбцы нужно было автоматически создавать время от времени.Иногда обычный пользователь не имеет прав на выполнение команд DDL.
У меня полностью динамически настраиваемое программное обеспечение, и количество значений, которые необходимо сохранить в таблице, зависит от конфигурационного файла этого программного обеспечения.Я выбрал эту модель, чтобы упростить ведение базы данных и передачу данных между системами.
Кроме того, я мог бы сказать, что различные значения должны сохраняться через свои интервалы.
Итак, я выигралне сдавайтесь EAV , поскольку он уже работает более эффективно, чем прежняя обычная таблица.
Нет необходимости представлять эту вертикальную структуру в виде горизонтальных строк данных, за исключением создания экспорта для устаревших систем.,И это как раз тема моего вопроса.