由于过滤需要 JOIN,避免出现多个重复记录

Avoid multiple duplicate records due to JOIN needed for filtering

所以我有三个简单的表格

create table user (
    id SERIAL PRIMARY KEY,
    name TEXT
);

create table item (
    user_id INTEGER REFERENCES user(id),
    key TEXT,
    count INTEGER
);

create table foob (
    user_id INTEGER REFERENCES user(id),
    value_f TEXT,
    value_t TEXT
);

我需要获取所有匹配特定项目和 foobs 的用户:

select id, name
from user
left join item on item.user_id = user.id
left join foob on foob.user_id = user.id
where item.key = 'my_key' and foob.value_t = 'vtz'

但这会导致同一结果的多个副本,因为 item and/or foob 有多行引用同一用户。由于我只使用其他两个表来过滤并且不需要在我的 select 中使用任何一个,我显然不需要多个复制结果。我怎样才能避免这种情况?

在我的真实代码中,我还使用 json_build_object() 和我的 select

最快的解决方法可能是 SELECT DISTINCT:

select distinct id, name
from user
left join item on item.user_id = user.id
left join foob on foob.user_id = user.id
where item.key = 'my_key' and foob.value_t = 'vtz'

另一种选择是在子查询中查找匹配的用户,使用:

with cte as (
    select t1.user_id
    from item t1
    inner join foob t2
        on t1.user_id = t2.user_id
    where t1.key = 'my_key' and t2.value_t = 'vtz'
)
select u.id, u.name
from user u
where u.id in (select user_id from cte)

您可能可以使用 ROW_NUMBER() 函数,例如

select * from (
select id, name, ROW_NUMBER () OVER (ORDER BY id) as rn
from user
left join item on item.user_id = user.id and item.key = 'my_key'
left join foob on foob.user_id = user.id
and foob.value_t = 'vtz' )xxx
where rn = 1;

没有JOIN的另一个选项:

select id, name
from user 
where user_id in (
    select user_id from item where key = 'my_key'
    UNION ALL
    select user_id form foob where value_t = 'vtz'
)

您可以只使用 GROUP BY "user".id(因为它是其 table 的主键,其 table 中的所有其他列在功能上都依赖于它)。

select    id, name
from      "user"
left join item on item.user_id = "user".id
left join foob on foob.user_id = "user".id
where     item.key = 'my_key' and foob.value_t = 'vtz'
group by  "user".id

顺便说一句,我不确定这些是不是您真正的 table 的名字。 Funny things happen if you select * from user.

我认为您可能 运行 陷入了一个称为断层陷阱的数据模型问题。