我正在尝试查找可能包含卷,问题或两者的项目的两个元数据(卷和问题)。元数据存储在具有项目ID,密钥(元数据字段ID)和值的表中。
这确实有效,但似乎过于复杂和重复:
select volume.text_value as volume_value, issue.text_value as issue_value
from metadatavalue item
left outer join (select item_id, text_value from metadatavalue
where metadata_field_id = 90) volume
on item.item_id = volume.item_id
left outer join (select item_id, text_value from metadatavalue
where metadata_field_id = 91) issue
on item.item_id = issue.item_id
where item.metadata_field_id in (90, 91)
有没有更简单的方法来编写此查询?
感谢。
答案 0 :(得分:2)
SELECT DISTINCT ON (item_id)
item_id,
CASE metadata_field_id
WHEN 90 THEN
text_value
ELSE (
SELECT text_value
FROM metadatavalue m
WHERE m.metadata_field_id = 90
AND m.item_id = i.item_id
)
END AS volume,
CASE metadata_field_id
WHEN 91 THEN
text_value
ELSE (
SELECT text_value
FROM metadatavalue m
WHERE m.metadata_field_id = 91
AND m.item_id = i.item_id
)
END AS issue
FROM metadatavalue
WHERE metadata_field_id IN (90, 91)
ORDER BY
item_id
在(item_id, metadata_field)
上建立索引可以改善此查询。
如果items
metadata
90
和91
items
与items
的总数相比较metadata
,则效果会更好。
如果几乎所有SELECT *
FROM (
SELECT item_id,
(
SELECT text_value
FROM metadatavalue m
WHERE m.metadata_field_id = 90
AND m.item_id = i.item_id
) volume,
(
SELECT text_value
FROM metadatavalue m
WHERE m.metadata_field_id = 91
AND m.item_id = i.item_id
) issue
FROM items
) q
WHERE issue IS NOT NULL OR volume IS NOT NULL
都拥有这些{{1}},请使用:
{{1}}
答案 1 :(得分:2)
试试这个
select volume.text_value as volume_value,
issue.text_value as issue_value
from metadatavalue item
left outer join metadatavalue volume
on item.item_id = volume.item_id
left outer join metadatavalue issue
on item.item_id = issue.item_id
where volume.metadata_field_id = 90
and issue.metadata_field_id = 91
答案 2 :(得分:2)
PostgreSQL支持完全外连接,可以简化查询:
select v.text_value as volume_value, i.text_value as issue_value
from ( select item_id, text_value
from metadatavalue
where metadata_field_id = 90) v
full join
( select item_id, text_value
from metadatavalue
where metadata_field_id = 91) i
using (item_id)
答案 3 :(得分:0)
使用case语句将值分隔为存储桶,max函数将允许text_value数据浮动到顶部。
select
item_id
,max(case metadata_field_id when 90 then text_value else null end) as volume_value
,max(case metadata_field_id when 91 then text_value else null end) as issue_value
from
metadatavalue
group by
item_id
以下是我用于测试目的的内容:
select
item_id
,max(case metadata_field_id when 90 then text_value else null end) as volume_value
,max(case metadata_field_id when 91 then text_value else null end) as issue_value
from
(
select 1 as item_id, 90 as metadata_field_id, '90-I am here' as text_value
union
select 1 as item_id, 91 as metadata_field_id, '91-Me too' as text_value
union
select 2 as item_id, 90 as metadata_field_id, null as text_value
union
select 2 as item_id, 91 as metadata_field_id, '91-funky' as text_value
union
select 3 as item_id, 90 as metadata_field_id, '90-fresh' as text_value
) metadatavalue
group by
item_id
结果:
item_id volume_value issue_value
1 90-I am here 91-Me too
2 NULL 91-funky
3 90-fresh NULL
注意:我使用SQL Server建模&测试然后更改语法以匹配Postgres。
答案 4 :(得分:0)
您可以将内部表中的谓词转换为连接条件:
select volume.text_value as volume_value, issue.text_value as issue_value
from metadatavalue item
left outer join metadatavalue volume
on volume.metadata_field_id = 90 and volume.item_id = item.item_id
left outer join metadatavalue issue
on issue.metadata_field_id = 91 and issue.item_id = item.item_id
where item.metadata_field_id in (90, 91)
虽然我不确定我是否理解了您的架构 - 但在我看来item
应该指的是与volume
和issue
不同的表格? ......更像是:
select item.*, volume.text_value as volume_value, issue.text_value as issue_value
from item
left outer join metadatavalue volume
on volume.metadata_field_id = 90 and volume.item_id = item.item_id
left outer join metadatavalue issue
on issue.metadata_field_id = 91 and issue.item_id = item.item_id
这也使得相当奇怪的地方条件消失了。您可以将上述查询放入视图(“item_volume_issue”)中,看起来卷和问题只是item_volume_issue中的其他列而不是单独的表(这对我来说更有意义)。