SQL 根据条件查询 return 个 table 个特定的匹配值

SQL Query to return a table of specific matching values based on a criteria

我在 PostgreSQL 数据库中有 3 个 table:

person (id, first_name, last_name, age)
interest (id, title, person_id REFERENCES person)
location (id, city, state text NOT NULL, country, person_id REFERENCES person)

city 可以为空,但 statecountry 不能。 一个人可以有很多兴趣,但只有一个地方。我的挑战是 return table 有相同兴趣和地点的人。

所有 ID 都已序列化并因此自动创建。 假设我有 4 个人住在“德克萨斯州”,他们每个人都有两个兴趣,但只有第 1 个人和第 3 个人有相似的兴趣,假设是“枪支”(毕竟是德克萨斯州)。我需要 select 来自人 table 的所有人,其中此人的兴趣标题(因为 ID 是自动生成的,两个 Guns 兴趣会导致两个不同的 ID 密钥)等于另一个人的兴趣标题和城市或州也是平等的。

我在看这个问题的答案Select Rows with matching columns from SQL Server,感觉逻辑和我的问题有点相似,不同的是他有两个table,连接在一起我有三个。

return a table of people who share the same interest and location.

我将其解释为 “来自 table person 的所有行,其中存在至少共享 interest 中的一个匹配行和一个匹配行的另一行排在位置上。没有特定的顺序。"

在子查询中使用 window 函数的简单解决方案:

SELECT p.*
FROM  (
   SELECT person_id AS id, i.title, l.city, l.state, l.country
        , count(*) OVER (PARTITION BY i.title, l.city, l.state, l.country) AS ct
   FROM   interest i
   JOIN   location l USING (person_id)
   ) x
JOIN   person p USING (id)
WHERE  x.ct > 1;

这将 NULL 值视为“相等”。 (你没有明确说明。)

根据未公开的基数,可能会有更快的查询样式。 (比如首先减少到重复的兴趣和/或位置。)

旁白 1:

拥有一个列 birthday(或 year_of_birth)几乎总是比 age 更好,后者会立即开始位腐烂。

旁白 2:

A person can have [...] only one location.

您至少可以在 location.person_id 上添加一个 UNIQUE 约束来强制执行。 (如果你不能让它成为 PK 或只是将位置列附加到 person table。)