我在users
表中有一个名为skills
的列,其类型为VARCHAR
,值为implod
,由PHP编写。例如1,2,3,4,5
我正在尝试制作作品列表,作品具有相同的技能组合(不同的ID ),每个work
都有自己的技能列,其格式与前一个。例如2,6,5,3,7
所以我想将这两个列与查询进行比较,看看作品是否具有用户的全部或部分技能,如果是,则显示它。
正如已发布的社区主题,我发现了FIND_IN_SET
或多个LIKE
语句的一些解决方案,但实际上它们不适合我的情况。
由于我不是查询粉丝,所以这种比较的最佳或最佳做法是什么?
答案 0 :(得分:3)
最佳解决方案是更改架构。不要在一列中存储多个值。用户和技能之间的关系是“多对多”的关系。对于任何多对多关系,您应该使用三个表:
users -- one record for each user
+----+------+
| id | name |
+----+------+
| 1 | Bob |
| 2 | Joe |
| 3 | Ken |
+----+------+
skills -- one record for each possible skill
+----+-------------+
| id | name |
+----+-------------+
| 1 | PHP |
| 2 | CSS |
| 3 | JS |
| 4 | MySQL |
+----+-------------+
userSkills -- relational table that maps skills to users
+--------+---------+
| userId | skillId |
+--------+---------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 1 | 4 |
| 2 | 2 |
| 2 | 3 |
| 2 | 4 |
| 3 | 1 |
| 3 | 4 |
+--------+---------+
现在,当您想要了解Joe的技能时,您可以执行以下查询:
SELECT
s.name
FROM
users u
INNER JOIN userSkills us
ON u.id = us.userId
INNER JOIN skills s
ON us.skillId = s.id
WHERE
u.name = 'Joe'
作品和技能之间的关系也是多对多的关系。我们还需要两个表,因为我们已经有了skills
表。
works
+----+-----------------------+
| id | name |
+----+-----------------------+
| 1 | Client-side developer |
| 2 | Server-side developer |
| 3 | All-around developer |
+----+-----------------------+
workSkills
+--------+---------+
| workId | skillId |
+--------+---------+
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 4 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
| 3 | 4 |
+--------+---------+
现在,您可以通过以下查询找到服务器端开发人员所需的所有技能:
SELECT
s.name
FROM
works w
INNER JOIN workSkills ws
ON w.id = ws.workId
INNER JOIN skills s
ON ws.skillId = s.id
WHERE
w.name = 'Server-side developer'
现在是棘手的部分。获取给定工作的用户列表。以下查询将为您提供具有与指定工作相同技能的用户列表。他们对这项工作的技能越多,他们的得分就越高:
SELECT
u.name,
COUNT(s.name) AS score
FROM
users u
INNER JOIN userSkills us
ON u.id = us.userId
INNER JOIN skills s
ON us.skillId = s.id
INNER JOIN workSkills ws
ON s.id = ws.skillId
INNER JOIN works w
ON ws.workId = w.id
WHERE
w.name = 'Server-side developer'
GROUP BY
u.name
ORDER BY
score DESC
输出:
+------+-------+
| name | score |
+------+-------+
| Bob | 2 | -- Bob has all four skills, but only PHP and MySQL are relevant
| Ken | 2 | -- Ken has PHP and MySQL skills, same as this work requires
| Joe | 1 | -- Joe has CSS, JS, and MySQL skills...only MySQL is relevant
+------+-------+
答案 1 :(得分:1)
我建议你不要让技能ids像那样崩溃。保留5个表格。
您将拥有干净且可扩展的结构,并且易于提取数据。
获取用户技能的SQL是
SELECT skillid, skillname FROM Skills INNER JOIN UsersSkills ON Skills.skillid = UsersSkills.skillid WHERE UserSkills.userid = 3
获取作品技巧的SQL
SELECT skillid, skillname FROM skills INNER JOIN workskills ON skills.skillid = workskills.skillid WHERE workskills.workid = 1
我们假设我们有这两个表
usersskills worksskills
+--------+---------+ +--------+-------+
|skillid | userid | |skillid |workid |
+--------+---------+ +--------+-------+
| 1 | 1 | | 1 | 3 |
| 2 | 1 | | 2 | 3 |
| 3 | 1 | | 3 | 3 |
| 4 | 1 | | 4 | 3 |
| 1 | 2 | | 5 | 3 |
| 2 | 2 | +--------+--------
+--------+---------+
这里我们有2个用户,第一个有4个技能,第二个有2个技能。我们的工作(身份3)需要5种不同的技能。
以下是此项工作的用户资格。
+--------+-------------+
|userid |scorepercent |
+--------+-------------+
|1 |80 |
|2 |40 |
+--------+-------------+
用户1的工作资格为80%,用户2资格为40%
SQL(简短和干净)
按分数排序的所有用户
select
userid,
(count(skillid) * 100 / (select count(*) from skillswork where workid = 3)) as score
from
skillsuser
where
skillid in (select skillid from skillswork where workid = 3)
group by
userid
order by
score desc
如果您不需要百分比,只需要一个简单的SQL
select
userid,
count(skillid) as score
from
skillsuser
where
skillid in (select skillid from skillswork where workid = 3)
group by
userid
order by
score desc
单个目标用户
select
userid,
(count(skillid) * 100 / (select count(*) from skillswork where workid = 3)) as score
from
skillsuser
where
skillid in (select skillid from skillswork where workid = 3)
and
userid = 1