Solution comme demandé
Bien que coincé avec cette conception malheureuse, la requête la plus rapide serait avec crosstab()
, fourni par le module supplémentaire tablefunc
. De nombreux détails dans cette réponse connexe :
Pour la question posée :
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);
Conception de la base de données
Si vous n'avez pas un énorme nombre de champs différents, ce sera beaucoup plus simple et plus efficace pour fusionner les trois tableaux en un seul tableau :
CREATE TABLE entry (
entry_id serial PRIMARY KEY
,field1 text
,field2 text
, ... more fields
);
Les champs sans valeurs peuvent être NULL
. NULL
le stockage est très bon marché (essentiellement 1 bit par colonne dans le bitmap NULL):
- Combien d'espace disque est nécessaire pour stocker une valeur NULL à l'aide de la base de données postgresql ?
- Do nullable les colonnes occupent de l'espace supplémentaire dans PostgreSQL ?
Même si vous avez des centaines de colonnes différentes et que seules quelques-unes sont remplies par entrée, cela utilisera toujours beaucoup moins d'espace disque.
Votre requête devient triviale :
SELECT entry_id, result, output, code, command
FROM enty;
Si vous avez trop de colonnes, et que ce n'est pas seulement une conception erronée (souvent, cela peut être plié en beaucoup moins de colonnes), considérez les types de données hstore
ou json
/ jsonb
(dans Postgres 9.4) pour EAV
stockage.
Par la page "À propos" de Postgres :
Maximum Columns per Table 250 - 1600 depending on column types
Considérez cette réponse connexe avec des alternatives :
Et cette question sur les cas d'utilisation/problèmes typiques des structures EAV sur dba.SE :