У меня есть две таблицы, которые выглядят ниже. В таблице employee вместо упоминания навыков напрямую, я использую в качестве ссылки из другой таблицы.
Вопрос :
select * from Employee where Skills = "1";
В приведенном выше запросе будет отображаться запись сотрудника, у которой ТОЛЬКО навык «Python». Конечно, он не покажет другую комбинацию, в которую включен Python, например, «1,2» (Python, Java). Как я могу достичь этого, не используя такой же оператор, поскольку в случае, если у меня есть 10, 11, 21 в навыках, это будет проблемой, не так ли.
Если вы считаете, что этот способ использования ссылки затруднен или не рекомендуется, пожалуйста, предложите вашу идею 🙂
Таблица сотрудников:
+-----+-------------+-------------+ | id | Name | Skills | +-----+-------------+-------------+ | 1 | Xyz | 1,2,4 | | 2 | Xyy | 1,3 | | 3 | Abc | 1,2,3 | | 4 | Asd | 1 | +-----+-------------+-------------+
Таблица навыков:
+-----+-------------+ | id | SkillSet | +-----+-------------+ | 1 | Python | | 2 | Java | | 3 | C | | 4 | PHP | +-----+-------------+
Рассмотрим следующее
mysql> select * from employee ; +------+------+--------+ | id | name | skills | +------+------+--------+ | 1 | xyz | 1,2,4 | | 2 | abc | 1,3 | | 3 | lmn | 1,2,3 | +------+------+--------+ 3 rows in set (0.00 sec) mysql> select * from skillset ; +------+----------+ | id | skillset | +------+----------+ | 1 | Python | | 2 | Java | | 3 | C | | 4 | PHP | +------+----------+ 4 rows in set (0.00 sec)
Эта структура похожа на вашу и делает запрос в этой ситуации, однако мы можем использовать find_in_set
но это довольно неэффективно, вот несколько примеров
mysql> select e.id, e.name, group_concat(s.skillset) as skillset from employee e join skillset s on find_in_set(s.id,e.skills) > 0 where find_in_set(1,e.skills) > 0 group by e.id ; +------+------+-----------------+ | id | name | skillset | +------+------+-----------------+ | 1 | xyz | Python,Java,PHP | | 2 | abc | C,Python | | 3 | lmn | Java,Python,C | +------+------+-----------------+ 3 rows in set (0.00 sec) select e.id, e.name, group_concat(s.skillset) as skillset from employee e join skillset s on find_in_set(s.id,e.skills) > 0 where find_in_set(2,e.skills) > 0 group by e.id ; +------+------+-----------------+ | id | name | skillset | +------+------+-----------------+ | 1 | xyz | Python,PHP,Java | | 3 | lmn | C,Java,Python | +------+------+-----------------+
Теперь правильная нормализация сделает жизнь намного проще и будет иметь следующую таблицу ассоциаций
mysql> select * from employee_skills; +------------+----------+ | idemployee | idskills | +------------+----------+ | 1 | 1 | | 1 | 2 | | 1 | 3 | | 2 | 1 | | 2 | 3 | | 3 | 1 | | 3 | 2 | | 3 | 3 | +------------+----------+
Теперь выполнение запроса будет намного более эффективным в этом случае
mysql> select e.id, e.name, s.skillset from employee e join employee_skills es on es.idemployee = e.id join skillset s on s.id = es.idskills where s.id = 1 ; +------+------+----------+ | id | name | skillset | +------+------+----------+ | 1 | xyz | Python | | 2 | abc | Python | | 3 | lmn | Python | +------+------+----------+
Используя последний подход, более сложные вычисления могут быть выполнены довольно легко.
Как упоминалось другими в комментариях, это не самый полезный выбор дизайна, поскольку он заставил бы его долгое время создавать простой интерфейс CRUD для взаимодействия с этими значениями.
Вы бы идеально:
таблица сотрудников:
+-----+-------------+ | id | name | +-----+-------------+ | 1 | Bob | | 2 | Mary | +-----+-------------++
таблица набора навыков:
+-----+-------------+ | id | skillset | +-----+-------------+ | 1 | Python | | 2 | Java | | 3 | C | | 4 | PHP | +-----+-------------+
таблица employee_skillset:
+-----+---------------+---------------+ | id | employee_id | skillset_id | +-----+---------------+---------------+ | 1 | 1 | 1 | | 2 | 1 | 2 | | 3 | 1 | 4 | | 4 | 2 | 1 | | 5 | 2 | 3 | +-----+---------------+---------------+
Тогда вы могли бы сделать:
SELECT * FROM employee e INNER JOIN employee_skillset es ON e.id = es.employee_id WHERE es.skillset_id = "1";
Вы можете использовать таблицу набора навыков в интерфейсе CRUD в качестве выбираемых / редактируемых вариантов.
РЕДАКТИРОВАТЬ:
Достаточно легко включить в нее ряд навыков, используя предложение IN :
WHERE es.skillset_id IN (1, 3, 4);