Rozwiązanie zgodnie z żądaniem
Podczas gdy utknąłem przy tym niefortunnym projekcie, najszybsze zapytanie byłoby przy użyciu crosstab()
, dostarczony przez dodatkowy moduł tablefunc
. Obszerne szczegóły w tej powiązanej odpowiedzi:
Na zadane pytanie:
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);
Projekt bazy danych
Jeśli nie masz wielkiego wielu różnych pól, będzie znacznie prostsze i wydajniejsze aby połączyć wszystkie trzy tabele w jedną prostą tabelę:
CREATE TABLE entry (
entry_id serial PRIMARY KEY
,field1 text
,field2 text
, ... more fields
);
Pola bez wartości mogą być NULL
. NULL
przechowywanie jest bardzo tanie (zasadniczo 1 bit na kolumnę w bitmapie NULL):
- Ile miejsca na dysku potrzeba do przechowywania wartości NULL przy użyciu postgresql DB?
- Nie dopuszczaj do zerowania kolumny zajmują dodatkowe miejsce w PostgreSQL?
Nawet jeśli masz setki różnych kolumn, a tylko kilka jest wypełnionych na wpis, nadal będzie to zużywać znacznie mniej miejsca na dysku.
Twoje zapytanie staje się trywialne:
SELECT entry_id, result, output, code, command
FROM enty;
Jeśli masz zbyt wiele kolumn i nie jest to tylko błędny projekt (często można to złożyć do znacznie mniejszej liczby kolumn), rozważ typy danych hstore
lub json
/ jsonb
(w Postgres 9.4) dla EAV
przechowywanie.
Maximum Columns per Table 250 - 1600 depending on column types
Rozważ tę powiązaną odpowiedź z alternatywami:
A to pytanie o typowe przypadki użycia/problemy struktur EAV na dba.SE: