2013-07-30 51 views
5

我想知道如何創建一個查詢,以篩選出基於內加入了一些成果。如何防止內部聯接查詢(Postgres的)重複

考慮以下數據:

formulation_batch 
----- 
id project_id name  
1 1   F1.1 
2 1   F1.2 
3 1   F1.3 
4 1   F1.all 

formulation_batch_component 
----- 
id formulation_batch_id component_id 
1 1      1 
2 2      2 
3 3      3 
4 4      1 
5 4      2 
6 4      3 
7 4      4 

我想用1 PROJECT_ID選擇所有formulation_batch記錄,與1或2。所以我運行下面的查詢COMPONENT_ID一個formulation_batch_component:

SELECT "formulation_batch".* 
FROM "formulation_batch" 
INNER JOIN "formulation_batch_component" 
ON "formulation_batch"."id" = "formulation_batch_component"."formulationBatch_id" 
WHERE "formulation_batch"."project_id" = 1 
    AND (("formulation_batch_component"."component_id" = 2 
     OR "formulation_batch_component"."component_id" = 1)) 

然而,這將返回一個重複的條目:

1;"F1.1" 
2;"F1.2" 
4;"F1.all" 
4;"F1.all" 

是否有方法可以修改此查詢,以便我只返回符合條件的唯一公式製品記錄記錄?

EG:

1;"F1.1" 
2;"F1.2" 
4;"F1.all" 

感謝您的時間!

回答

7

一種方法是使用distinct

SELECT distinct "formulation_batch".* 
FROM "formulation_batch" 
INNER JOIN "formulation_batch_component" 
ON "formulation_batch"."id" = "formulation_batch_component"."formulationBatch_id" 
WHERE "formulation_batch"."project_id" = 1 
    AND (("formulation_batch_component"."component_id" = 2 
     OR "formulation_batch_component"."component_id" = 1)) 
+0

謝謝,我忘了是不同的。它並不是最明智的表現,但仍然比在軟件層面進行過濾要好。 – drkstr1

10

在這種情況下,可以應用join可能以前distinct使其更高性能:

select fb.* 
from 
    formulation_batch fb 
    inner join 
    (
     select distinct formulationbatch_id 
     from formulation_batch_component 
     where component_id in (1, 2) 
    ) fbc on fb.id = fbc.formulationbatch_id 
where fb.project_id = 1 

注意如何使用別名爲表名使查詢更清晰。另外in運營商非常方便。沒有必要使用帶有這些標識符的雙引號。

+0

感謝您對優化的想法。實際上是由一個ORM生成的查詢,但我認爲我有辦法實現它這樣的,而不是(在多我修改了它選擇的外部查詢不同的方式相同)。 – drkstr1

+0

在我的測試,innerjoining像上面也比where子句,即,使用formulationbatch_ids更快: '選擇FB * 從 formulation_batch FB 其中fb.project_id = 1 AND fb.id IN( 選擇formulationbatch_id 從formulation_batch_component 其中COMPONENT_ID在(1,2) )' –

2

我知道這個問題是問如何防止重複使用內部聯接,但可以在謂詞使用IN子句。

SELECT "formulation_batch".* 
FROM "formulation_batch" fb 
ON "formulation_batch"."id" = "formulation_batch_component"."formulationBatch_id" 
WHERE "formulation_batch"."project_id" = 1 
AND fb.id IN (SELECT "formulation_batch"."id" 
       FROM formulation_batch_component 
       WHERE (("formulation_batch_component"."component_id" = 2 
         OR "formulation_batch_component"."component_id" = 1)) 
+0

這是我試圖問這個問題的最佳解決方案。乾杯! – drkstr1

+0

我在我的情況下測試了這一點,並@Clodoaldo內託的回答,內側連接了〜50%的速度 –