订购具有最匹配用户技能的用户

时间:2015-02-07 18:23:22

标签: php mysql

我希望按照技能最匹配的降序向用户显示推荐用户。

问题是我在这种形式的单一领域存储技能

    user_skill
    musician,pop,singer

注意:这将是输入音乐家,流行音乐,歌手......

所以我想要实现的目标我希望向用户展示顶部的所有三种技能,然后是那些只有两种技能的用户。

所以out put就像

 **user_name    skills**

 sam     musician,pop,singer
 smith   musician,pop,singer
 ali     musician,singer
 nasira  musicain,pop
 siri    musician
 taylor  pop
 andrew  singer

这可以通过单个mysql查询来实现吗?

如果这不可能,可以通过php代码完成。我不想更改表结构,因为这需要大量的重做。

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

您可能可以使用SQL,但查询会非常复杂,我可能不会。

在php方面,您可以迭代结果集并计算您正在寻找的给定技能组中每个user_name的技能,然后对它们进行排序:

$desired = explode(',', $input);
$users = array();

// i presume you have the query worked out to find users with any one of input 
// skills attributed to them so lets say that $stmt is the PDO statement where you 
// have executed that query

while (false === ($row = $stmt->fetch(PDO::FETCH_ASSOC))) {
    $row['skills'] = explode(',', $row['skills']);
    // assign an array containing only skills that were in your $input
    // to $row['desired_skills']
    $row['desired_skills'] = array_intersect($desired, $row['skills']);
    $row['nb_desired_skills'] = count($row['desired_skills']);
    $user[] = $row;
}

usort($users, function ($a, $b) {
    return $b['nb_desired_skills'] - $a['nb_desired_skills'];
});

// now you can loop over $users and display the fields you need

但是,这些技能的定义和归属是您应用程序的关键部分,您现在应该对表进行规范化...它只会通过关闭它来成为更大的重构。

答案 1 :(得分:1)

  

我不想更改表结构,因为这需要大量重做。

强烈(!) 建议你制作一个单独的skills表,然后使用外键将其链接到users表。一旦你的项目变得更加复杂,你将无限感激自己。

如果你不知道怎么做,我相信如果你要发布另一个问题,这个网站上的人会帮你做一个转换的脚本。

<强>的MySQL

CREATE TABLE skills
(
       name VARCHAR(64) NOT NULL,
    user_id INT NOT NULL,
    PRIMARY KEY (name, user_id),
    FOREIGN KEY (user_id) REFERENCES users(id)
);

通过这种方式,您可以使用简单的子查询轻松通过大多数技能选择用户(假设您有一个users列,其中包含id列:

<强>的MySQL

SELECT *,
       (SELECT COUNT(*)
          FROM skills
         WHERE user_id = u.id) AS num_skills
  FROM users u
 ORDER BY num_skills DESC;

那你为什么要采用这种方法而不是依赖PHP?

  • 在数据库中创建最小的额外开销
  • 显着 减少数据库和网络服务器之间的聊天,如果您只想要,例如,只需要排名前10位的用户,则无需查询整个用户表,
  • 将来可以轻松实现更复杂和变化的查询。

以下MySQL代码段仅 查询具有特定技能的用户(例如“歌手”),然后根据技能数量按降序排序。查询不会返回零技能的用户:

<强>的MySQL

SELECT *,
       (SELECT COUNT(*)
          FROM skills
         WHERE user_id = u.id
           AND name = 'singer') AS num_skills
  FROM users u
 WHERE num_skills > 0
 ORDER BY num_skills DESC;

当然,您也可以通过id搜索技能,只需将子查询中的WHERE子句的第二部分替换为AND id = 3,这将查询那些拥有ID为3的技能。


更优化数据库的下一步是创建一个真实的skills表,它只存储您在数据库中注册的技能,以及一个user_skills表,用于链接它和users一起表。

这将使您能够 显着 从长远来看减少数据库大小,并且能够运行不依赖于Web服务器的复杂但“干净”的查询。