MySQL多重利益匹配问题

时间:2011-05-06 03:04:56

标签: mysql loops for-loop

我有一个用户输入兴趣的数据库。我想找到兴趣相符的人。

兴趣表的结构是

interestid | username | hobby | location | level | matchinginterestids

让我们让两个用户保持简单。

  • 用户Joe可能有10条不同的兴趣记录
  • 用户greg可能有10个不同的兴趣记录。

我想做以下算法

  • 获取Joe的兴趣记录1,并从兴趣数据库中寻找匹配的爱好和位置。将任何匹配的兴趣ID放在匹配字段中。然后去乔的兴趣记录2等。

我想我需要的是某种for循环,它会循环遍历所有joe的内容,然后每次在兴趣数据库中找到匹配项时进行更新。这在MySQL中甚至可能吗?


进一步的例子:

我是丹。我有3个兴趣。每个兴趣由3个科目组成:

  • 丹猫,营养,头发
  • Dan superlens,dna,显微镜
  • 丹电影,慢动作,fightscenes

其他人可能有其他兴趣

乔:

  • 乔猫,营养,力量
  • Joe superlens,dna,显微镜

  • Moe mysql,查询,php
  • Moe电影,specialfx,相机
  • Moe superlens,dna,显微镜

现在,当我以Dan身份登录时,我希望查询返回以下内容:

以下是您感兴趣的内容:

---对猫营养毛有兴趣 乔对猫和营养感兴趣 Joe和Moe对超透镜,dna,显微镜感兴趣 Moe对电影感兴趣

查询需要遍历Dan的所有兴趣,并比较3,2,1个主题匹配。

我可以在循环中在php中执行此操作,但它会一直调用数据库来获取结果。我想知道是否有一种狡猾的方式来使用单个查询或者可能是3个单独的查询,一个查找3个匹配,一个用于2,一个用于1。

2 个答案:

答案 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再次有一个用于链接的主键和一些信息字段
(嗯,只是一个,但那是因为这是一个例子)

请注意,usersinterests没有任何关联 那很奇怪,为什么呢? 好吧有一个问题......一个user可以有多个intrests intrests可以属于多个people。 我们可以通过更改为用户表来解决这个问题:

TABLE users (id, username, location, intrest1, intrest2, intrest3)

但这是一个糟糕的,非常糟糕的主意,因为:

  1. 这样每个用户只允许3个兴趣
  2. 如果许多用户有2个,1个或没有兴趣
  3. ,这是浪费空间
  4. 最重要的是,它使查询难以编写。
  5. 用于链接错误用户表

    的示例查询
    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
    

    为什么这样更好?

    1. 每位用户无限数量的利益,反之亦然
    2. 如果用户生活枯燥,兴趣很少,则不会浪费空间
    3. 查询维护更简单
    4. 让它变得有趣

      只是列出所有用户并不是很有趣,因为那时我们仍然需要处理php或其他任何数据。但是没有必要这样做,毕竟SQL是一种查询语言所以让我们问一个问题:

        

      向所有与用户Moe分享兴趣的用户

      好的,让我们制作一本食谱并收集我们的食材。我们需要什么。

      我们有一个user“Moe”,我们有其他user个,但“Moe”。 我们对他们有共同的兴趣 我们还需要链接表userInterest,因为这是我们关联userinterests的方式。

      让我们先列出所有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

      相匹配的爱好的用户

      希望这有帮助。