Php 订购最匹配用户的用户';s技能

Php 订购最匹配用户的用户';s技能,php,mysql,Php,Mysql,我想以降序向用户显示推荐用户,其中技能最匹配 问题是我在这个表单中存储单个领域的技能 user_skill musician,pop,singer 注:这将是输入音乐家、流行音乐人、歌手 所以,我想要实现的是,我想向用户展示三种技能的最高水平,然后是那些拥有两种技能的用户,最后是那些只有一种技能的用户 所以,我们会像 **user_name skills** sam musician,pop,singer smith musician,pop,sing

我想以降序向用户显示推荐用户,其中技能最匹配

问题是我在这个表单中存储单个领域的技能

    user_skill
    musician,pop,singer
注:这将是输入音乐家、流行音乐人、歌手

所以,我想要实现的是,我想向用户展示三种技能的最高水平,然后是那些拥有两种技能的用户,最后是那些只有一种技能的用户

所以,我们会像

 **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代码完成。我不想改变表结构,因为这将需要大量的重做


谢谢您的帮助。

您可能可以使用SQL,但是查询太复杂了,我可能不会

在php端,您可以迭代结果集,并在给定的技能集中统计每个用户名的技能,然后对它们进行排序:

$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
然而,这些技能的定义和属性是您应用程序的关键部分,您现在应该规范化这些表。。。它只会因为推迟而变成一个更大的重构

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

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

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

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)
);
SELECT *,
       (SELECT COUNT(*)
          FROM skills
         WHERE user_id = u.id) AS num_skills
  FROM users u
 ORDER BY num_skills DESC;
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
列的
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)
);
SELECT *,
       (SELECT COUNT(*)
          FROM skills
         WHERE user_id = u.id) AS num_skills
  FROM users u
 ORDER BY num_skills DESC;
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;

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

  • 在数据库中创建最小的额外开销
  • 如果只想查询前10名用户,则无需查询整个用户表,从而显著减少了数据库和Web服务器之间的聊天
  • 在将来轻松实现更复杂和更多变的查询
下面的MySQL代码片段只查询具有给定技能的用户(例如,“singer”),然后根据技能的数量按描述顺序对其进行排序。查询不会返回技能为零的用户:

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)
);
SELECT *,
       (SELECT COUNT(*)
          FROM skills
         WHERE user_id = u.id) AS num_skills
  FROM users u
 ORDER BY num_skills DESC;
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
子句的第二部分替换为
和id=3
,这将查询id为3的技能用户


实现更优化数据库的下一步是创建一个真正的
skills
表,该表仅存储您在数据库中注册的技能,以及一个
user\u skills
表,将其与
users
表链接在一起


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

您可以使用SQL,但查询太复杂,我可能不会。在php端,您可以迭代结果集,并在给定的技能集中统计每个用户名的技能,然后对它们进行排序。然而,这些技能的定义和属性是您应用程序的关键部分,您现在应该规范化这些表。。。如果推迟的话,它只会变成一个更大的重构。谢谢。让我试试上面的。谢谢它的工作。但是你是对的,我应该尝试创建另一个表。嗨,我意识到你是非常正确的。你能告诉我什么查询将达到我的要求吗。假设我有以上技能,因此我希望在我的推荐页面顶部看到用户具有最相似的技能。您编写的查询没有在where子句中使用任何技能。您当然可以将
where
添加到主查询或子查询中。如果我理解正确,你的问题不需要一个。您想要一个不列出某个技能计数以下的用户的示例(
主查询中的WHERE
),还是一个忽略某个技能的示例(
子查询中的WHERE
)?顺便说一句,上述查询创建一个技能表(第一个查询),然后做一个
选择
,根据技能的数量以降序返回所有用户。是的,请我想要一个例子,其中用户拥有与我相同的全部或任何技能。然后以用户拥有最匹配技能的方式排序,依此类推。因此我假设在where子句中,我将传递技能的ID。。。不确定,但像这样,用户的技能id(3,4,5)。。