简体   繁体   English

Postgresql:替代多次连接同一张表

[英]Postgresql : Alternative to joining the same table multiple times

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. 如果我有两个表entryentry_metadata ,其中entry_metadata作为由entry_id和变量引用的条目的描述表。

If i have this : 如果我有这个:

entry 条目

id | name   |
-------------
1  | entry1 |
2  | entry2 |
3  | entry3 |

entry_metadata 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 : 通过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. 但是随着我添加更多变量以从条目元数据中获取值(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? 有办法解决这个问题吗?

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. 添加其他列只是添加更多的聚合功能。

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. 因此,对于每个新变量,您只需要再添加一个子选择。

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. 是的,更换entry_metadata在addtional列的表entry (可能的解决方案是hstorejsonb )与关键-项元数据的值存储。

Btw. 顺便说一句。 your tables represents well known controversial database desing pattern known as "Entity Attribute Value". 您的表代表了众所周知的有争议的数据库设计模式,称为“实体属性值”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM