我有一个包含两个表的 postgres 数据库:services
和 meta
。
第一个表存储应用程序所需的“核心”信息,应用程序还实现了一个“自定义字段”功能,其实现方式类似于 Wordpress 的 wp_post_meta
表的工作方式。
用户可以在与服务的一对多关系中添加具有任意键和值的元行。
元表的架构是:
这对应用程序非常有用,所以我对更改架构不感兴趣,但是对于一些不常使用的管理仪表板,我需要取回一个服务列表,其中几个元行作为列加入 。
这是我目前所拥有的:
SELECT
services.*,
meta1.value AS funding,
meta2.value AS ownership
FROM services
JOIN meta meta1
ON services.id = meta.service_id
AND meta.key = 'Funding'
JOIN meta meta2
ON services.id = meta2.service_id
AND meta2.key = 'Ownership'
现在,这很好用,但每次我想添加另一个元值时,我都必须再做一次连接。
这似乎会减慢查询速度并降低其可读性。
有没有什么好的方法可以重构它以使其易于阅读和快速运行?
这里尝试使用 OR 进行重构,但不起作用:
SELECT
*,
meta.value AS funding,
meta.value AS ownership
FROM services
JOIN meta
ON services.id = meta.service_id
AND meta.key = 'Funding' OR meta.key = 'Ownership'
答案 0 :(得分:0)
一种方法是将键/值对聚合为带有派生表的 JSON 值:
select srv.*,
mv.vals ->> 'Funding' as funding,
mv.vals ->> 'Ownership' as ownership
from services srv
cross join lateral (
select jsonb_object_agg(m.key, m.value) as vals
from meta m
where m.key in ('Funding', 'Ownership')
and m.service_id = srv.id
) as mv
如果您的应用程序可以处理 JSON,那么可能实际上不需要转换为两个单独的列,这将避免重复键。
答案 1 :(得分:0)
您可以使用条件聚合:
SELECT s.*, m.funding, m.ownership
FROM services s JOIN
(SELECT m.service_id,
MAX(value) FILTER (WHERE key = 'Funding') as Funding,
MAX(value) FILTER (WHERE key = 'Ownership') as Ownership
FROM meta m
GROUP BY m.service_id
) m
ON m.service_id = s.id