使用连接从 table 获取记录,其中连接中的记录不包含特定值
Get records from table with join where records in join not contain specific value
我有两个 table:
Table 用户:
create table user (
id bigserial not null primary key,
username varchar(256),
active boolean not null default true
);
和table地址:
create table address (
id bigserial not null primary key,
user_id integer not null,
country varchar(256),
city varchar(256),
street varchar(256)
);
以一些数据为例:
insert into user(id, username, active) values (1, 'john', true);
insert into user(id, username, active) values (2, 'alex', true);
insert into user(id, username, active) values (3, 'alice', true);
insert into user(id, username, active) values (4, 'tom', true);
insert into user(id, username, active) values (5, 'dave', true);
insert into address(id, user_id, country, city, street) values (1, 1, 'Germany', 'Berlin', '');
insert into address(id, user_id, country, city, street) values (2, 2, 'Germany', 'Berlin', '');
insert into address(id, user_id, country, city, street) values (3, 2, 'Great Britain', 'London', '');
insert into address(id, user_id, country, city, street) values (4, 3, 'France', 'Paris', '');
insert into address(id, user_id, country, city, street) values (5, 4, 'USA', 'New York', '');
insert into address(id, user_id, country, city, street) values (6, 5, 'South Korea', 'Seoul', '');
每个用户可以有多个地址。我需要让所有在他们的地址集中没有特定国家地址的用户,例如 'Germany'.
我尝试了什么:
select u.* from user u
left join address a on u.id=a.user_id where a.country is not like '%Germany%'
但是 returns 用户,他们有特定国家的地址但也有其他地址,哪个国家与特定国家不同,例如上面使用的数据是 alex,他有两个地址德国和英国:
id username active
--------------------
2 alex True
3 alice True
4 tom True
5 dave True
有什么建议可以让我做这样的查询吗?
您的代码检查每个用户是否至少有一个德国以外的地址,而您要确保他们有 none.
我会推荐 not exists
:
select c.*
from client c
where not exists (
select 1
from address a
where a.user_id = c.id and a.country = 'Germany'
)
此查询将利用 address(user_id, country)
上的索引。
注意不清楚你的table叫user
还是client
...我用的是后者
请注意,这也 returns 根本没有地址的客户端。如果这不是您想要的,那么另一种方法是使用聚合:
select c.*
from client c
inner join address on a.user_id = c.id
group by c.id
having not bool_or(a.country = 'Germany')
这是查询:
select user_id from address where country = 'Germany'
returns 您要过滤掉的所有用户。
与 NOT IN
:
一起使用
select u.*
from user u
where id not in (select user_id from address where country = 'Germany')
参见demo。
结果:
> id | username | active
> -: | :------- | :-----
> 3 | alice | t
> 4 | tom | t
> 5 | dave | t
我有两个 table:
Table 用户:
create table user (
id bigserial not null primary key,
username varchar(256),
active boolean not null default true
);
和table地址:
create table address (
id bigserial not null primary key,
user_id integer not null,
country varchar(256),
city varchar(256),
street varchar(256)
);
以一些数据为例:
insert into user(id, username, active) values (1, 'john', true);
insert into user(id, username, active) values (2, 'alex', true);
insert into user(id, username, active) values (3, 'alice', true);
insert into user(id, username, active) values (4, 'tom', true);
insert into user(id, username, active) values (5, 'dave', true);
insert into address(id, user_id, country, city, street) values (1, 1, 'Germany', 'Berlin', '');
insert into address(id, user_id, country, city, street) values (2, 2, 'Germany', 'Berlin', '');
insert into address(id, user_id, country, city, street) values (3, 2, 'Great Britain', 'London', '');
insert into address(id, user_id, country, city, street) values (4, 3, 'France', 'Paris', '');
insert into address(id, user_id, country, city, street) values (5, 4, 'USA', 'New York', '');
insert into address(id, user_id, country, city, street) values (6, 5, 'South Korea', 'Seoul', '');
每个用户可以有多个地址。我需要让所有在他们的地址集中没有特定国家地址的用户,例如 'Germany'.
我尝试了什么:
select u.* from user u
left join address a on u.id=a.user_id where a.country is not like '%Germany%'
但是 returns 用户,他们有特定国家的地址但也有其他地址,哪个国家与特定国家不同,例如上面使用的数据是 alex,他有两个地址德国和英国:
id username active
--------------------
2 alex True
3 alice True
4 tom True
5 dave True
有什么建议可以让我做这样的查询吗?
您的代码检查每个用户是否至少有一个德国以外的地址,而您要确保他们有 none.
我会推荐 not exists
:
select c.*
from client c
where not exists (
select 1
from address a
where a.user_id = c.id and a.country = 'Germany'
)
此查询将利用 address(user_id, country)
上的索引。
注意不清楚你的table叫user
还是client
...我用的是后者
请注意,这也 returns 根本没有地址的客户端。如果这不是您想要的,那么另一种方法是使用聚合:
select c.*
from client c
inner join address on a.user_id = c.id
group by c.id
having not bool_or(a.country = 'Germany')
这是查询:
select user_id from address where country = 'Germany'
returns 您要过滤掉的所有用户。
与 NOT IN
:
select u.*
from user u
where id not in (select user_id from address where country = 'Germany')
参见demo。
结果:
> id | username | active
> -: | :------- | :-----
> 3 | alice | t
> 4 | tom | t
> 5 | dave | t