我的mysql表中有列Student_hobbys:
student_hobbys
1|0|1|1|0|0|1|0
现在,我尝试搜索所有喜欢地理(学校学科)的学生。在“ student_hobbys”列中,我将此值保存在第二个参数(1 | here | 0 | 1 | ...)中。如何创建一个mysql查询来选择喜欢地理的学生?
请帮助
答案 0 :(得分:1)
请阅读here,为什么您的设计不是一个好主意。您应该按照以下方式normalized来存储数据:
桌子学生:
id | name
1 | John
2 | Jane
3 | Mike
4 | Spike
餐桌爱好:
id | name
1 | biology
2 | geogryphy
3 | football
4 | programming
表Students_hobies:
student_id | hobby_id
1 | 3
1 | 4
2 | 1
2 | 2
3 | 1
3 | 2
3 | 4
4 | 3
模式定义:
CREATE TABLE students (
id INT UNSIGNED AUTO_INCREMENT,
name VARCHAR(50),
PRIMARY KEY (id),
INDEX (name)
);
CREATE TABLE hobbies (
id INT UNSIGNED AUTO_INCREMENT,
name VARCHAR(50),
PRIMARY KEY (id),
INDEX (name)
);
CREATE TABLE students_hobbies (
student_id INT UNSIGNED,
hobby_id INT UNSIGNED,
PRIMARY KEY (student_id, hobby_id),
INDEX (hobby_id, student_id)
);
现在您的SELECT查询将是:
SELECT s.*
FROM students s
JOIN students_hobbies sh ON sh.student_id = s.id
JOIN hobbies h ON h.id = sh.hobby_id
WHERE h.name = 'geogryphy';
结果:
| id | name |
| --- | ---- |
| 2 | Jane |
| 3 | Mike |
但是-如果您想坚持自己的设计,可以尝试执行以下操作:
SELECT *
FROM students
WHERE student_hobbys LIKE '_|1%'
但是以编程方式生成此查询会非常复杂。在大数据集上,它可能也比上述解决方案要慢,因为无法对这种查询使用索引。
如果要避免在应用程序中使用复杂的代码,则将需要更为复杂的查询。一种方法是将字符串转换为位掩码,然后使用位运算符&
来检查特定位置的位:
SET @hobby_position = 2;
SELECT *
FROM students
WHERE CONV(REVERSE(REPLACE(student_hobbys, '|', '')), 2, 10) & 1 << (@hobby_position - 1);
| id | name | student_hobbys |
| --- | ---- | --------------- |
| 2 | Jane | 1|1|1|1|0|0|1|0 |
| 3 | Mike | 1|1|1|1|0|0|1|0 |
还有其他方法-但是您不太可能找到一种可以与您的设计配合使用的简单方法。