2016-12-13 126 views
0

假设我需要一个名为skills的字段,它应该存储一个人的各种技能,如php,java,Golang搜索包含多个值的字段

什么是适当的方法来在数据库中存储这些数据,以便使其由技能更容易

编辑1

用户可以输入任何他想要的技能搜索,上面只是一个例子

用户可以在文本框中键入一个或多个技能,用逗号

分离实施例

skill1,skill2,skill3 
+0

也许你可以提供你的**编辑1 **的含义的例子。 – gmiley

+0

不明白为什么这是downvoted!这是使用'SET'列的情况的一个很好的例子。 – cFreed

回答

0

什么是适当的方式存储在 数据库,数据

你应该有一个单独的表叫Skills,所有的技能应该存在,它也应该有一个FOREIGN KEY引用父表PRIMARY KEY字段。

这样,在需要的时候可以JOIN与父表和GROUP BY父表键字段,并得到所有相关的技能

2

你或许应该重新审视自己的设计方法(如果要列出所有技能GROUP_CONCAT())和将这些技能存储在名为skills的相关表中,其中列skill_idskill_nameskill_desc等...然后使用交叉参考表来链接您的人员表中的person_idskills表中的skill_id

如果无法执行的重新设计,你可以使用查询的一系列LIKE电话:

SELECT * 
FROM people 
WHERE skills LIKE '%php%' 
    OR skills LIKE '%java%' 
    OR skills LIKE '%Golang%'; 

但是,这是相当马虎。我会去重新设计。使用LIKE将会否定索引的好处。

要扩展上述多个表格,当用户键入逗号分隔技能列表时,需要将其解析为一个集合/数组,然后检查它们是否存在于新的skills表中。如果它不存在,则插入它。然后,或者如果确实存在,则拉skill_id并将其插入person_skills_xref表中,其中person_id(如果该组合尚不存在)。

这样你就可以做,然后像一个select语句:

SELECT s.skill_id, s.skill_name, s.skill_desc 
FROM skills s 
JOIN people_skills_xref ps 
ON s.skill_id = ps.skill_id 
WHERE ps.person_id = @personID; 

,将让你所有的技能与@personIDperson_id的人。

或者你也可以与特定skill_id用下面的查询选择所有在people表的人:

SELECT p.person_id, p.person_name, p.person_email 
FROM people p 
JOIN people_skills_xref ps 
ON ps.person_id = p.person_id 
WHERE ps.skill_id = @skillId; 

或者通过skill_name使用LIKE

SELECT p.person_id, p.person_name, p.person_email 
FROM people p 
JOIN people_skills_xref ps 
ON ps.person_id = p.person_id 
JOIN skills s 
ON s.skill_id = ps.skill_id 
WHERE s.skill_name LIKE @skillName; 

@skillName将包含一个搜索字符串'%sql'以匹配以sql结尾的任何内容,例如mysqlpl/sql,或只是sql

+0

检查编辑...用户可以输入任何技能,所以我不知道技能事先 – user2650277

+0

我不知道如何改变我的建议。通过'people_skills_xref'表,通过'people'与'skills'之间的M:M关系,您可以将任意数量的技能以任意组合方式应用于任意数量的人员。另外你不会重复你的技能。 “技能”表中只需要一个条目。 – gmiley

1

你应该使用3个表:

User 
----------------- 
id 
name 

Skill 
----------------- 
id 
name 

User_Skill 
----------------- 
user_id 
skill_id 

表用户包含所有用户,表技能包含了所有可用的技能和表User_Skills加入两个表。所以,如果你想添加一个技能给用户,你应该在表User_Skill中插入值。

如果你想获取一个用户的所有技巧,你可以使用:

select s.* from Skills s left join User_Skills us on us.skill_id = s.id where us.user_id = <insert user id>; 
+0

[_Optimal Many:Many table schema_](http://mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table)。 –

1

IMO您所需要的更简单的(和容易使用,在同一时间)的方法是使用一个唯一的列SET类型。

它是如何工作的基本总结:现场的

  • 定义:像skills SET('php','java','goLang',...)

  • 填充字段(一次与一个或多个技能):UPDATE table SET skills = 'php, java'

  • 寻找一个给定的技能:SELECT * FROM table WHERE FIND_IN_SET('java', skills) > 0

看看这个MySQL page,假设MariaDB应该提供相同的功能。

重要提示:我认为这是唯一给你所需要的强大,因为一些你不明确你的任择议定书表示方法,但可能是一个要求:给定的人可能有几个技能

2日重要提示:OP的编辑状态

用户可以输入任何他想要的技能

这是唯一的地步SET不起作用直接根据需要,因为不同的可能值必须在列定义级别注册(但显然可以更新以进化)。
因此,如果用户想要提及一些当前未知的技能,则必须向他提供一种“声明”这种新技能的注册方法,然后将其注册在定义列中,并实际更新用户skills字段。

+0

声称的方法似乎很棒... ... stackoverflow风格:) – user2650277

+0

@ user2650277作为一个非母语英语的演讲者,我不知道我的话是怎么回事:从您的评论我猜我没有选择正确的方式来表达.. 。我也很快写了这个答案,所以它有点缩写。我所说的“声称”是:用户应该有一个建议的(注册)技能列表,他将从哪里选择他想要的内容。而这个列表应该包含诸如'other'之类的东西,当它被选择时会导致输入区域输入新技能。然后,您的后端脚本应该检测到这种情况并相应地进行处理(在更新表之前修改列表)。 – cFreed

+0

我完全理解你的意思。我想说的是,stackoverflow也使用你提到的建议系统 – user2650277