Я работаю в системе, где у нас есть произвольные входящие данные, хранящиеся в структуре таблицы, которая в основном является хранилищем на основе значений ключей.
Структура таблицы в действительности немного сложнее, но для решения проблемы я приведу упрощенный пример:
CREATE TABLE records (id BIGINT, type TEXT, identifier TEXT);
CREATE TABLE record_items (id BIGINT, rec_id BIGINT, key TEXT, value TEXT);
INSERT INTO records VALUES (10, 'PERSON', 'P12823');
INSERT INTO record_items VALUES
(11, 10, 'FIRST_NAME', 'James'),
(12, 10, 'LAST_NAME', 'Burwell'),
(13, 10, 'AGE', '76'),
(14, 10, 'HEIGHT', '5-9'),
(15, 10, 'WEIGHT', '149'),
(16, 10, 'BLOOD', 'A+');
INSERT INTO records VALUES (20, 'PERSON', 'P83494');
INSERT INTO record_items VALUES
(21, 20, 'FIRST_NAME', 'David'),
(22, 20, 'LAST_NAME', 'McDonnell'),
(23, 20, 'AGE', '47'),
(24, 20, 'COMPANY', 'Super Saver Foods');
INSERT INTO records VALUES (30, 'PERSON', 'P81323');
INSERT INTO record_items VALUES
(31, 30, 'FIRST_NAME', 'William'),
(32, 30, 'LAST_NAME', 'Nelson'),
(32, 30, 'HEIGHT', '5-6'),
(33, 30, 'VEHICLE', '2005 Dodge Charger');
Как видите, входящие данные имеют произвольные ключи. Есть некоторые ключи, которые присутствуют для всех входящих данных, а затем есть некоторые, которые изменяются от записи к записи, а некоторые отсутствуют:
SELECT r.id, r.type, r.identifier, ri.key, ri.value
FROM records r
JOIN record_items ri ON ri.rec_id = r.id
ORDER BY r.id, ri.key
id | type | ident | key | value
-------------------------------------------
10 | PERSON | P12823 | AGE | 76
10 | PERSON | P12823 | BLOOD | A+
10 | PERSON | P12823 | FIRST_NAME | James
10 | PERSON | P12823 | HEIGHT | 5-9
10 | PERSON | P12823 | LAST_NAME | Burwell
10 | PERSON | P12823 | WEIGHT | 149
20 | PERSON | P83494 | AGE | 47
20 | PERSON | P83494 | COMPANY | Flix
20 | PERSON | P83494 | FIRST_NAME | David
20 | PERSON | P83494 | LAST_NAME | Donnell
30 | PERSON | P81323 | FIRST_NAME | William
30 | PERSON | P81323 | HEIGHT | 5-6
30 | PERSON | P81323 | LAST_NAME | Nelson
30 | PERSON | P81323 | VEHICLE | Dodge
Однако нам нужно получить все эти произвольные строки, транспонированные в столбцы (порядок столбцов не важен):
id | identifier | first_name | last_name | age | height | weight | company | vehicle
-----------------------------------------------------------------------------------
10 | P12823 | James | Burwell | 76 | 5-9 | 149 | |
20 | P83494 | David | Donnell | 47 | | | Flix |
30 | P81323 | William | Nelson | | 5-6 | | | Dodge
Мне известно о существовании функции crosstab
, однако я не смог заставить ее работать так, как нам нужно. Основная проблема заключается в том, что, насколько я понимаю, crosstab
ожидает, что все записи имеют одинаковые ключи в одинаковом порядке, а любые отсутствующие или произвольные ключи смешивают набор результатов. Другая проблема, связанная с crosstab
, заключается в том, что мне нужно явно определить столбцы для набора результатов, но нам нужно иметь возможность вызывать функцию аналогично следующему:
SELECT *
FROM some_crosstab_like_function('PERSON') -- PERSON identifies record type
Я думаю о создании какого-либо механизма, который состоит из функций и временных таблиц или представлений, которые создаются на лету и возвращают необходимые данные. Однако, прежде чем продолжить, я хотел бы узнать, есть ли другое, более простое решение моей проблемы.
Мы являемся PostgreSQL 10.5.
Любые идеи будут высоко оценены.