Решение според искането
Въпреки че сте останали с този неудачен дизайн, най-бързата заявка би била с crosstab()
, предоставен от допълнителния модул tablefunc
. Достатъчно подробности в този свързан отговор:
За зададения въпрос:
SELECT * FROM crosstab(
$$SELECT e.id, ef.name, ef.value
FROM entry e
LEFT JOIN entry_fields ef
ON ef.entryid = e.id
AND ef.name = ANY ('{result,output,code,command}'::text[])
ORDER BY 1, 2$$
,$$SELECT unnest('{result,output,code,command}'::text[])$$
) AS ct (id int, result text, output text, code text, command text);
Дизайн на база данни
Ако нямате огромен брой различни полета, ще бъде много по-просто и по-ефективно за да обедините всичките три таблици в една проста таблица:
CREATE TABLE entry (
entry_id serial PRIMARY KEY
,field1 text
,field2 text
, ... more fields
);
Полетата без стойности могат да бъдат NULL
. NULL
съхранението е много евтино (основно 1 бит на колона в NULL bitmap):
- Колко дисково пространство е необходимо за съхраняване на NULL стойност с помощта на postgresql DB?
- Направете nullable колоните заемат допълнително място в PostgreSQL?
Дори ако имате стотици различни колони и само няколко са попълнени на запис, това пак ще използва много по-малко дисково пространство.
Вашето запитване става тривиално:
SELECT entry_id, result, output, code, command
FROM enty;
Ако имате твърде много колони и това не е просто погрешен дизайн (често това може да се сгъне в много по-малко колони), помислете за типовете данни hstore
или json
/ jsonb
(в Postgres 9.4) за EAV
съхранение.
На страница „Относно“ на Postgres :
Maximum Columns per Table 250 - 1600 depending on column types
Помислете за този свързан отговор с алтернативи:
И този въпрос относно типични случаи на употреба/проблеми на EAV структури на dba.SE: