2009-06-05 49 views
2

我正在嘗試查找可能有卷,問題或兩者兼有的項目的兩個元數據(卷和問題)。元數據存儲在具有項目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) 

有沒有寫這個查詢一個更簡單的方法?

謝謝。

+1

查詢似乎是錯擺在首位,你必須使用項目ID的加入! – tekBlues 2009-06-05 17:13:12

+0

看媽媽,不要自我加入!在下面查看我的解決方案。 ;) – tom 2009-06-05 17:37:32

+0

我確實在連接中使用了物品ID。我所忘記的是一個DISTINCT。 – 2009-06-05 17:37:43

回答

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) 
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)將改善此查詢。

這將更好地工作,如果有幾個items9091metadata,相比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 
+0

好的,謝謝。第一個查詢似乎只是我的重述,但更好的格式化:-)確實很少有卷/問題的項目。 – 2009-06-05 17:36:32

+0

@Nicholas:嗯......我糾正了一下,以避免重複的查詢。 – Quassnoi 2009-06-05 17:41:09

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 
0

使用case語句來分隔值入桶,最大的功能將允許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 。

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) 

雖然我不知道我做你的schema--的意義上,它在我看來,應該item是指與volumeissue不同的表格嗎?更多類似於:

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」)中,看起來volume和issue只是item_volume_issue中的附加列而不是單獨的表格(這對我來說更有意義)。