由于过滤需要 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
.
我认为您可能 运行 陷入了一个称为断层陷阱的数据模型问题。
所以我有三个简单的表格
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
.
我认为您可能 运行 陷入了一个称为断层陷阱的数据模型问题。