我在MySQL数据库中有一个表,其中包含那些人居住的人的'pid'和城市city
的ID。因为每个人在他/她的生活中都可能住在一个以上的城市,一个人可以在该表中有多个条目。
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
我想知道两件事/三件事:
pid
是什么?
(结果应为[1,2,4])如何设计查询,找出这些内容(而不是过度压缩我的数据库服务器)?
答案 0 :(得分: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
子选择回答第一个问题,它只能获得他们居住在纽约 AND 柏林的pid
。
由于子选择每pid
只会返回一行,我们必须再次将结果pid
加入到表中以回答问题2(让所有城市都住在pid
那些住在纽约和柏林的人。如果用户既住在纽约和柏林,也不住在任何其他城市,我们不想排除该pid,因此我们使用LEFT JOIN
。如果没有其他城市,city
字段将只是No other cities
。
现在,无论pid
如何,我们都要计算整个表格中城市显示的次数,我们会再次在city
字段上自行加入表格。当此联接发生时,pid -> city
的组合将显示为表格中该城市的多次,因此为了获得计数,我们GROUP BY
pid
和city
{1}},其中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
答案 1 :(得分: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并计数以获得实际计数: