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服务器之间的聊天
- 在将来轻松实现更复杂和更多变的查询
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)。。