PostgreSQL 选择加入不在列表中

Ask*_*613 1 sql postgresql join

该项目正在使用 Postgres 9.3

我有如下表格(我已经简化了):

t_person (30 million records)
- id
- first_name
- last_name
- gender

t_city (70,000 records)
- id
- name
- country_id

t_country (20 records)
- id
- name

t_last_city_visited (over 200 million records)
- person_id
- city_id
- country_id
  - There is a unique constraint on person_id, country_id to
    ensure that each person only has one last city per country
Run Code Online (Sandbox Code Playgroud)

我需要做的是以下方面的变化:

获取访问过“英国”国家但从未访问过“美国”国家的女性人的 id

我尝试了以下方法,但速度太慢。

select t_person.id from t_person
join t_last_city_visited
  on (
          t_last_city_visited.person_id = t_person.id
          and country_id = (select id from t_country where name = 'UK')
     )
where gender = 'female'
except
(
    select t_person.id from t_person
    join t_last_city_visited
      on (
             t_last_city_visited.person_id = t_person.id
             and country_id = (select id from t_country where name = 'USA')
         )
)
Run Code Online (Sandbox Code Playgroud)

我真的很感激任何帮助。

Dav*_*dge 5

提示:您在这里要做的是找到存在访问英国但不存在访问美国的女性。

就像是:

select ...
from   t_person
where  ...
   and exists (select null
                 from t_last_city_visited join
                      t_country on (...)
                where t_country.name = 'UK')
   and not exists (select null
                 from t_last_city_visited join
                      t_country on (...)
                where t_country.name = 'US')
Run Code Online (Sandbox Code Playgroud)

另一种方法,找到访问过英国而不是美国的人,然后你可以加入这些人以按性别过滤:

select   person_id
  from   t_last_city_visited join
         t_country on t_last_city_visited.country_id = t_country.id
 where   t_country.name in ('US','UK')
group by person_id
having   max(t_country.name) = 'UK'
Run Code Online (Sandbox Code Playgroud)