-2

替代文字

对于一个特定的名字,我想获取住在这个人居住的三个或更多城市的其他名字。

4

9 回答 9

12

这是你应该做的:

重新设计您的数据库以拥有一个城市表:

city(id int, name varchar)

和一个用户表:

user(id int, name varchar, ...)

和一个 user_city 表:

user_city(user_id int, city_id int)

仅此一项就可以消除每位用户 10 个城市的限制。

查找用户居住的城市:

select city_id form user_city where user_id = ?

现在您将如何从该列表中找到居住在 3 个或更多城市的用户?一种方法是计算每个用户居住的列表中的城市数量,例如:

select user_id,count(*) n 
from user_city 
where city_id in (select city_id 
                  from user_city 
                  where user_id = ?) 
group by user_id having n >= 3;

我没有真正测试这个,但它应该工作。

您还必须弄清楚如何索引这些表。

于 2010-03-18T09:05:33.223 回答
4

您需要binomial(10,3)^2OR 条件来进行查询。那是 14 400。你不想那样做。

于 2010-03-18T12:32:09.437 回答
2

你需要重新设计你的桌子而不是

名称 , 城市 1 , 城市 2 , 城市 3 , 城市 4 , 城市 5 , 城市 6 , 城市 7 , 城市 8 , 城市 9 城市 10

它应该更像

Person, City, rank
------------------
name , city1 ,1
name , city2 ,2 
name , city3 ,3 
name , city4 ,4 
name , city5 ,5 
name , city6 ,6 
name , city7 ,7 
name , city8 ,8 
name , city9 ,9 
name , city10,10

并听取 TomTom 的建议并学习数据规范化!

于 2010-03-18T08:57:48.627 回答
2

尊重您不重新设计数据库的要求

我没有尝试过的想法,现在没有办法测试它

select name, c1通过联合等创建视图(名称,城市)select name, c2......

然后:

select m2.name from myview m1
inner join myview m2 on m1.city = m2.city
where m1.name = @Name AND m2.Name!=@Name
group by m2.name
having count(m2.name) > 2 
于 2010-03-18T12:33:13.087 回答
1

是的。

您将表格发回给设计它的人并附上评论,以了解如何设计表格。第一个范式,归一化。

一旦表遵循 SQL 规则,查询就很容易了。

于 2010-03-18T08:53:50.257 回答
1

尝试这样的事情:

SELECT PersonName,COUNT(*) AS CountOf
    FROM (SELECT PersonName,city1 FROM PersonCities WHERE city1 IS NOT NULL
          UNION SELECT PersonName,city2 FROM PersonCities WHERE city2 IS NOT NULL
          UNION SELECT PersonName,city3 FROM PersonCities WHERE city3 IS NOT NULL
          UNION SELECT PersonName,city4 FROM PersonCities WHERE city4 IS NOT NULL
          UNION SELECT PersonName,city5 FROM PersonCities WHERE city5 IS NOT NULL
          ...
         ) dt
    WHERE dt.city1 IN (SELECT city1 FROM PersonCities WHERE PersonName=..SearchPerson.. AND city1 IS NOT NULL
                       UNION SELECT city2 FROM PersonCities WHERE PersonName=..SearchPerson.. AND city2 IS NOT NULL
                       UNION SELECT city3 FROM PersonCities WHERE PersonName=..SearchPerson.. AND city3 IS NOT NULL
                       UNION SELECT city4 FROM PersonCities WHERE PersonName=..SearchPerson.. AND city4 IS NOT NULL
                       UNION SELECT city5 FROM PersonCities WHERE PersonName=..SearchPerson.. AND city5 IS NOT NULL
                       ...
                       )
        AND PersonName!=@SearchPerson
    GROUP BY PersonName
    HAVING COUNT(*)>=3

我没有 mysql,所以这里使用 SQL Server 运行:

DECLARE @PersonCities table(PersonName varchar(10), city1 varchar(10), city2 varchar(10), city3 varchar(10), city4 varchar(10), city5 varchar(10))
INSERT INTO @PersonCities VALUES ('Joe','AAA','BBB','CCC', NULL, NULL)
INSERT INTO @PersonCities VALUES ('Pat','BBB','DDD','EEE','FFF','GGG')
INSERT INTO @PersonCities VALUES ('Sam','FFF','BBB', NULL, NULL, NULL)
INSERT INTO @PersonCities VALUES ('Ron','HHH','DDD','EEE','FFF', NULL)
INSERT INTO @PersonCities VALUES ('Don','FFF','ZZZ','QQQ', NULL, NULL)

DECLARE @SearchPerson varchar(10)
SET @SearchPerson='Pat'

SELECT PersonName,COUNT(*) AS CountOf
    FROM (SELECT PersonName,city1 FROM @PersonCities WHERE city1 IS NOT NULL
          UNION SELECT PersonName,city2 FROM @PersonCities WHERE city2 IS NOT NULL
          UNION SELECT PersonName,city3 FROM @PersonCities WHERE city3 IS NOT NULL
          UNION SELECT PersonName,city4 FROM @PersonCities WHERE city4 IS NOT NULL
          UNION SELECT PersonName,city5 FROM @PersonCities WHERE city5 IS NOT NULL
         ) dt
    WHERE dt.city1 IN (SELECT city1 FROM @PersonCities WHERE PersonName=@SearchPerson AND city1 IS NOT NULL
                       UNION SELECT city2 FROM @PersonCities WHERE PersonName=@SearchPerson AND city2 IS NOT NULL
                       UNION SELECT city3 FROM @PersonCities WHERE PersonName=@SearchPerson AND city3 IS NOT NULL
                       UNION SELECT city4 FROM @PersonCities WHERE PersonName=@SearchPerson AND city4 IS NOT NULL
                       UNION SELECT city5 FROM @PersonCities WHERE PersonName=@SearchPerson AND city5 IS NOT NULL
                       )
        AND PersonName!=@SearchPerson
    GROUP BY PersonName
    HAVING COUNT(*)>=3

输出:

PersonName 
---------- -----------
Ron        3

(1 row(s) affected)
于 2010-03-18T12:56:31.747 回答
0

将这些数据分解为三个表,以提供更灵活的多对多关系。

person存储名称的
city表 存储城市的表以将
person_city两者关联起来(多对多)

检索居住在 navin 拥有的 3 个或更多城市的其他人:

SELECT name FROM (
    SELECT
        p.name, COUNT(DISTINCT(city_id)) AS lived
    FROM person p 
    JOIN person_city pc ON (pc.person_id = p.person_id) 
    JOIN city c ON (c.city_id = pc.city_id) 
    WHERE city_id IN (
        SELECT c2.city_id 
        FROM city c2 
        JOIN person_city pc2 ON (c2.city_id = pc2.city_id) 
        JOIN person p2 ON (p2.person_id = pc2.person_id) 
        WHERE p2.name = 'navin' 
    )
    GROUP BY person_id HAVING lived >= 3
) AS multihome 
WHERE name <> 'navin';
于 2010-03-18T12:18:53.450 回答
0

您需要规范化您的数据库。

这样做你会得到列

名称,城市(可选 CityOrder)。

之后,您将需要找到一种方法将这些结果组合成您需要的结果。这样做你需要了解 Join、Count 和 Group by。

于 2010-03-18T08:56:19.177 回答
0

尝试这个:

<table> Person
<fields> PersonId, PersonName |

<table> City
<fields> CityId, CityName |

<table> LivedIn
<fields> LivedInId, PersonId, CityId

从逻辑上讲,您将为每个场景执行以下操作:

  1. 查找居住在最多不同城市的人:
    列出 PersonId(所有人)的列表
    遍历该列表并计算每个人居住的城市数量
    查找任何人居住的最多城市
    查找人名与拥有最多城市的 personId 相关

  2. 查找所有居住在 3 个或更多城市的人作为给定人
    让我们称此人 Bob
    列出 Bob 居住的所有城市(CityIds)。
    创建一个包含 personId 和常见城市的列表(可能是 Java 中的 HashMap )
    遍历 LivedIn 表并更新有多少个城市是共同
    的 找到所有计数大于 3 的人

我会使用 Java 和 SQL 的组合来做到这一点,但我对任何一种都不是很好,所以不能在这里给你代码,而不必查找很多东西。

于 2010-03-18T09:11:50.700 回答