首页 > 解决方案 > 从带有连接的表中获取记录,其中连接中的记录不包含特定值

问题描述

我有两张桌子:

表用户:

create table user (
   id bigserial not null primary key,
   username varchar(256),
   active boolean not null default true
);

和表地址:

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', '');

每个用户可以有多个地址。我需要让所有地址集中没有特定国家/地区地址的用户,例如“德国”。

我尝试了什么:

select u.* from user u
left join address a on u.id=a.user_id where a.country is not like '%Germany%'

但它返回的用户有特定国家的地址但也有其他地址,哪个国家与特定国家不同,例如上面使用的数据是 alex,他有两个地址德国和英国:

id  username  active
--------------------
2   alex      True
3   alice     True
4   tom       True
5   dave      True

有什么建议我该怎么做这样的查询?

标签: sqlpostgresqlcountsubquery

解决方案


您的代码检查每个用户是否至少有一个德国以外的地址,而您要确保他们没有。

我会推荐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).

请注意,不清楚您的表是被调用user还是client......我使用了后者。

请注意,这也会返回根本没有地址的客户端。如果这不是您想要的,那么另一种方法使用聚合:

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')

推荐阅读