我有一个用户输入兴趣的数据库。我想找到兴趣相符的人。
兴趣表的结构是
interestid | username | hobby | location | level | matchinginterestids
让我们让两个用户保持简单。
我想做以下算法
我想我需要的是某种for循环,它会循环遍历所有joe的内容,然后每次在兴趣数据库中找到匹配项时进行更新。这在MySQL中甚至可能吗?
进一步的例子:
我是丹。我有3个兴趣。每个兴趣由3个科目组成:
其他人可能有其他兴趣
现在,当我以Dan身份登录时,我希望查询返回以下内容:
以下是您感兴趣的内容:
---对猫营养毛有兴趣 乔对猫和营养感兴趣 Joe和Moe对超透镜,dna,显微镜感兴趣 Moe对电影感兴趣
查询需要遍历Dan的所有兴趣,并比较3,2,1个主题匹配。
我可以在循环中在php中执行此操作,但它会一直调用数据库来获取结果。我想知道是否有一种狡猾的方式来使用单个查询或者可能是3个单独的查询,一个查找3个匹配,一个用于2,一个用于1。
答案 0 :(得分:5)
这绝对可以用于MySQL,但我认为你可能会以一种尴尬的方式来解决这个问题。我将从结构化表开始,如下所示:
TABLE Users ( userId, username, location )
TABLE Interests( interestId, hobby )
TABLE UserInterests( userId, interestId, level )
当用户添加兴趣时,如果之前未添加兴趣,则将其添加到Interests
表,然后将其添加到UserInterests
表。当您想要检查其他具有相似兴趣的人时,您可以简单地在UserInterests
表中查询其他具有相似兴趣的人,这些人已经为您提供了所有这些信息:
SELECT DISTINCT userId
FROM UserInterests
WHERE interestId IN (
SELECT interestId
FROM UserInterests
WHERE userId = $JoesID
)
这可以在没有子查询的情况下以更优雅的方式完成,但这是我现在想到的。
答案 1 :(得分:4)
根据丹尼尔的特殊要求,虽然它有点重复,但没关系。
架构解释
TABLE User (id, username, location )
TABLE Interests(id, hobby )
TABLE UserInterest(userId, interestId, level )
表users
在开头只有用户数据和主键字段:id
主键字段是纯链接字段,其他字段是信息字段。
表Interest
再次有一个用于链接的主键和一些信息字段
(嗯,只是一个,但那是因为这是一个例子)
请注意,users
和interests
没有任何关联
那很奇怪,为什么呢?
好吧有一个问题......一个user
可以有多个intrests
, intrests
可以属于多个people
。
我们可以通过更改为用户表来解决这个问题:
TABLE users (id, username, location, intrest1, intrest2, intrest3)
但这是一个糟糕的,非常糟糕的主意,因为:
用于链接错误用户表
的示例查询SELECT * FROM user
INNER JOIN interests ON (user.intrest1 = interests.id) or
(user.intrest2 = interests.id) or
(user.intrest3 = interests.id);
这只是一个列出所有用户及其兴趣的简单查询 随着事情的发展,它很快变得非常复杂。
多对多关系
解决多对多关系问题的方法是使用链接表 这将多对多关系减少为两个一对多关系。
答:1 userinterest
到许多user
的
B:1 userinterest
到许多interests
使用链接表的示例查询
SELECT * FROM user
INNER JOIN userInterest ON (user.id = userInterest.userID) //many-to-1
INNER JOIN interest ON (interest.id = userInterest.InterestID); //many-to-1
为什么这样更好?
让它变得有趣
只是列出所有用户并不是很有趣,因为那时我们仍然需要处理php或其他任何数据。但是没有必要这样做,毕竟SQL是一种查询语言所以让我们问一个问题:
向所有与用户Moe分享兴趣的用户
好的,让我们制作一本食谱并收集我们的食材。我们需要什么。
我们有一个user
“Moe”,我们有其他user
个,但不“Moe”。
我们对他们有共同的兴趣
我们还需要链接表userInterest
,因为这是我们关联user
和interests
的方式。
让我们先列出所有Moe的爱好
SELECT i_Moe.hobby FROM interests AS i_Moe
INNER JOIN userInterests as ui2 ON (ui2.InterestID = i_Moe.id)
INNER JOIN user AS u_Moe ON (u_Moe.id = ui2.UserID)
WHERE u_Moe.username = 'Moe';
现在我们将所有用户的选择与Moe的爱好相结合。
SELECT u_Others.username FROM interests AS i_Others
INNER JOIN userinterests AS ui1 ON (ui1.interestID = i_Others.id)
INNER JOIN user AS u_Others ON (ui1.user_id = u_Others.id)
/*up to this point this query is a list of all interests of all users*/
INNER JOIN Interests AS i_Moe ON (i_Moe.Hobby = i_Others.hobby)
/*Here we link Moe's hobbies to other people's hobbies*/
INNER JOIN userInterests as ui2 ON (ui2.InterestID = i_Moe.id)
INNER JOIN user AS u_Moe ON (u_Moe.id = ui2.UserID)
/*And using the link table we link Moe's hobbies to Moe*/
WHERE u_Moe.username = 'Moe'
/*We limited user-u_moe to only 'Moe'*/
AND u_Others.username <> 'Moe';
/*and the rest to everybody except 'Moe'*/
因为我们在链接字段上使用INNER JOIN
,所以只会考虑匹配,并且会抛弃不匹配。
如果您用英语阅读查询,就会这样。
考虑所有不是Moe
的用户,将其称为U_others
考虑用户Moe
,称他为U_Moe
考虑用户Moe
的爱好,称之为i_Moe
考虑其他用户的爱好,称之为i_Others
现在将i_Others
爱好与u_Moe
的爱好相关联
仅返回U_Others
中具有与Moe
希望这有帮助。