如何使用内部联接查询防止重复(Postgres)

时间:2013-07-30 23:40:04

标签: sql postgresql inner-join

我正在尝试了解如何创建查询以根据内部联接过滤掉一些结果。

考虑以下数据:

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

我想选择project_id为1的所有formula_batch记录,并且有一个component_batch_component,其component_id为1或2.所以我运行以下查询:

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"

有没有办法修改此查询,以便我只返回符合条件的唯一formula_batch记录?

EG:

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

谢谢你的时间!

3 个答案:

答案 0 :(得分:12)

在这种情况下,可以在distinct之前应用join,使其更具性能:

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运算符非常方便。不需要使用带有这些标识符的双引号。

答案 1 :(得分:8)

一种方法是使用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 ))

答案 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 ))