Reputation: 2104
If i have two tables entry and entry_metadata, with the entry_metadata as a description table for the entry referenced by entry_id and a variable.
If i have this :
entry
id | name |
-------------
1 | entry1 |
2 | entry2 |
3 | entry3 |
entry_metadata
id | entry_id | variable | value
1 | 1 | width | 10
2 | 1 | height | 5
3 | 2 | width | 8
4 | 2 | height | 7
5 | ... | .... | ..
and i'm getting the table :
id | name | width | height| ... | ...
-----------------------------------------
1 | entry1 | 10 | 5 |
2 | entry2 | 8 | 7 |
3 | entry3 | .. | .. |
by the sql :
select e.name, em.width, emr.height
from
public.entry e
left join
public.entry_metadata em
on
em.entry_id = e.id and em.variable = 'width'
left join
public.entry_metadata emr
on
emr.entry_id = e.id and emr.variable = 'height'
The query above works. But as I add more variables to get the values (the entry_metadata table includes a large variety of variables) from the entry metadata. The query gets really really slow. every join I do slows down the execution greatly. Is there a way to get around this?
Upvotes: 0
Views: 1731
Reputation: 4774
Is there a way to get around this?
Yes, replace entry_metadata
table with addtional column in entry
(possible solutions are hstore
or jsonb
) with key - value storage of entry metadata.
Btw. your tables represents well known controversial database desing pattern known as "Entity Attribute Value".
Upvotes: -1
Reputation: 287
Just use subselects for this:
SELECT
e.id,
e.name,
(SELECT em.value FROM public.entry_metadata em WHERE em.entry_id = e.id AND em.variable = 'width') AS width,
(SELECT em.value FROM public.entry_metadata em WHERE em.entry_id = e.id AND em.variable = 'height') AS height
FROM
public.entry e
So for each new variable you just need to add one more subselect.
Upvotes: 1
Reputation: 1269483
You can also do this with conditional aggregation:
select id, name,
max(case when variable = 'width' then value end) as width,
max(case when variable = 'height' then value end) as height
from public.entry_metadata em
group by id, name;
Adding additional columns is just adding more aggregation functions.
Upvotes: 2