2

我在 MySQL 数据库中有一个表,其中包含人的 ID 'pid' 和city这些人居住的城市的名称。由于每个人在他/她的生活中可能住在多个城市,一个人可以拥有多个该表中的条目。

PID | CITY
1   | Berlin
1   | New York

2   | Berlin
2   | Oslo
2   | New York
2   | Mexiko City

3   | Oslo

4   | Berlin
4   | Oslo
4   | Bagdad
4   | New York
4   | Mexiko City

我想知道两/三件事:

  1. 那些pid住在“柏林”和“纽约”的人是谁(结果应该是 [1, 2, 4])
  2. 人们居住的其他城市是什么,曾经居住在“柏林”和“纽约”(结果应该是[“奥斯陆”,“墨西哥城”,“巴格达”])
  3. 获得计数会更好,这些城市在表格中出现的频率。(结果应该是 ["Oslo" -> 2 , "Mexiko City" -> 2, "Bagdad" -> 1])

我如何设计我的查询,找出这些东西(而不是让我的数据库服务器压力过大)?

4

2 回答 2

2

您可以在一个查询中完成所有这些操作:

SELECT
    a.pid,
    COALESCE(b.city, 'No other cities') AS othercity,
    COUNT(c.city) AS OverallCityCount
FROM
    (
        SELECT pid
        FROM tbl
        WHERE city IN ('New York', 'Berlin')
        GROUP BY pid
        HAVING COUNT(*) = 2
    ) a
LEFT JOIN
    tbl b ON a.pid = b.pid AND b.city NOT IN ('New York', 'Berlin')
LEFT JOIN
    tbl c ON b.city = c.city
GROUP BY
    a.pid, 
    b.city

子选择FROM回答问题一,它只得到他们在纽约柏林pid都住过的地方。

由于子选择每 只返回一行pid,因此我们必须pid再次将结果 s 与表连接以回答问题 2(获取所有居住在pid纽约和柏林的 s 的城市)。如果用户居住在纽约和柏林,但不是任何其他城市,我们不想排除那个 pid,所以我们使用LEFT JOIN. 如果没有其他城市,则该city字段将是No other cities

现在要计算该城市在表中出现的次数,无论pid,我们再次在表上自加入city字段。当这个连接发生时, 的组合pid -> city将出现与表中那个城市一样多的次数,所以为了得到计数,我们GROUP BYpidcity其中COUNT()给出了城市出现次数的计数桌子。如果没有pid居住过的其他城市,则此计数将为 0。

使用您的示例数据,结果集将如下所示:

pid | othercity        | OverallCityCount
-----------------------------------------
1   | No other cities  | 0
2   | Oslo             | 3
2   | Mexiko City      | 2
4   | Oslo             | 3
4   | Bagdad           | 1
4   | Mexiko City      | 2

http://www.sqlfiddle.com/#!3/2bb23/2/0

于 2012-06-25T19:06:37.807 回答
2

1) 搜索两个城市pid,通过统计列表中匹配城市的记录数,并检查是否等于匹配城市的总数,找到所有匹配所有城市的城市。

select
  pid
from
  PlacesLived
where
  city in ('Berlin', 'New York')
group by
  pid
having
  count(*) = 2

演示:http ://www.sqlfiddle.com/#!3/645ea/1


2) 查询 (1) 中发现的人们居住的不同城市列表,减去您要验证的城市(柏林和纽约):

select distinct
  city
from
  PlacesLived
where pid in (
  select
    pid
  from
    PlacesLived
  where
    city in ('Berlin', 'New York')
  group by
    pid
  having
    count(*) = 2
)
and city not in ('Berlin', 'New York')

演示:http ://www.sqlfiddle.com/#!3/645ea/3


3)添加 group by 和 count 以获得实际计数:

演示:http ://www.sqlfiddle.com/#!3/645ea/4

于 2012-06-25T19:07:19.897 回答