Возможно, вы захотите взглянуть на мой предыдущий вопрос .
Моя схема базы данных выглядит так
--------------- ---------------
| candidate 1 | | candidate 2 |
--------------- \ --------------
/ \ |
------- -------- etc
|job 1| | job 2 |
------- ---------
/ \ / \
--------- --------- --------- --------
|company | | skills | |company | | skills |
--------- --------- ---------- ----------
Вот моя база данных:
mysql> describe jobs;
+--------------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------+------+-----+---------+----------------+
| job_id | int(11) | NO | PRI | NULL | auto_increment |
| candidate_id | int(11) | NO | MUL | NULL | |
| company_id | int(11) | NO | MUL | NULL | |
| start_date | date | NO | MUL | NULL | |
| end_date | date | NO | MUL | NULL | |
+--------------+---------+------+-----+---------+----------------+
.
mysql> describe candidates;
+----------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+----------+------+-----+---------+----------------+
| candidate_id | int(11) | NO | PRI | NULL | auto_increment |
| candidate_name | char(50) | NO | MUL | NULL | |
| home_city | char(50) | NO | MUL | NULL | |
+----------------+----------+------+-----+---------+----------------+
.
mysql> describe companies;
+-------------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+---------------+------+-----+---------+----------------+
| company_id | int(11) | NO | PRI | NULL | auto_increment |
| company_name | char(50) | NO | MUL | NULL | |
| company_city | char(50) | NO | MUL | NULL | |
| company_post_code | char(50) | NO | | NULL | |
| latitude | decimal(11,8) | NO | | NULL | |
| longitude | decimal(11,8) | NO | | NULL | |
+-------------------+---------------+------+-----+---------+----------------+
.
Обратите внимание, что мне, вероятно, следует называть это skill_usage
, поскольку это указывает, когда навык был используйте don a job.
mysql> describe skills;
+----------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+---------+------+-----+---------+-------+
| skill_id | int(11) | NO | MUL | NULL | |
| job_id | int(11) | NO | MUL | NULL | |
+----------+---------+------+-----+---------+-------+
.
mysql> describe skill_names;
+------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+----------+------+-----+---------+----------------+
| skill_id | int(11) | NO | PRI | NULL | auto_increment |
| skill_name | char(32) | NO | MUL | NULL | |
+------------+----------+------+-----+---------+----------------+
До сих пор мой запрос MySQL выглядел так:
SELECT DISTINCT can.candidate_id,
can.candidate_name,
can.candidate_city,
j.job_id,
j.company_id,
DATE_FORMAT(j.start_date, "%b %Y") AS start_date,
DATE_FORMAT(j.end_date, "%b %Y") AS end_date,
s.skill_id
FROM candidates AS can
INNER JOIN jobs AS j ON j.candidate_id = can.candidate_id
INNER JOIN companies AS co ON j.company_id = co.company_id
INNER JOIN skills AS s ON s.job_id = j.job_id
INNER JOIN skill_names AS sn ON s.skill_id = s.skill_id
AND sn.skill_id = s.skill_id
ORDER by can.candidate_id, j.job_id
Я получаю результат как это, но меня это не устраивает.
+--------------+----------------+---------------------+--------+------------+------------+------------+----------+
| candidate_id | candidate_name | candidate_city | job_id | company_id | start_date | end_date | skill_id |
+--------------+----------------+---------------------+--------+------------+------------+------------+----------+
| 1 | Pamela Brown | Cardiff | 1 | 3 | 2019-01-01 | 2019-08-31 | 1 |
| 1 | Pamela Brown | Cardiff | 1 | 3 | 2019-01-01 | 2019-08-31 | 2 |
| 1 | Pamela Brown | Cardiff | 1 | 3 | 2019-01-01 | 2019-08-31 | 1 |
| 1 | Pamela Brown | Cardiff | 2 | 2 | 2018-06-01 | 2019-01-31 | 3 |
| 1 | Pamela Brown | Cardiff | 3 | 1 | 2017-11-01 | 2018-06-30 | 4 |
| 1 | Pamela Brown | Cardiff | 3 | 1 | 2017-11-01 | 2018-06-30 | 5 |
| 1 | Pamela Brown | Cardiff | 3 | 1 | 2017-11-01 | 2018-06-30 | 6 |
| 1 | Pamela Brown | Cardiff | 4 | 3 | 2016-08-01 | 2017-11-30 | 1 |
| 2 | Christine Hill | Salisbury | 5 | 2 | 2018-02-01 | 2019-05-31 | 3 |
Теперь я хотел бы ограничить поиск, указав «навык», например Python, C, C ++, UML и т. д. c и названия компаний
Пользователь вводит что-то вроде Python AND C++
в поле поиска навыков (и / или Microsoft OR Google
в поле поиска по названию компании).
Как ввести это в мой запрос? Имейте в виду, что с каждым идентификатором навыка связан идентификатор задания. Может быть, мне сначала нужно преобразовать имена навыков из поиска (в данном случае Python C++
) в идентификаторы навыков? Тем не менее, как мне включить это в свой запрос?
Чтобы прояснить несколько моментов:
- и поле поиска навыков и компании может быть пустым, что я буду интерпретировать как "вернуть все"
- поисковые запросы могут включать ключевые слова И и ИЛИ с группировочными скобками (НЕ требуется). Я достаточно счастлив, чтобы проанализировать это в PHP и превратить его в термин запроса MySQL (моя трудность только с SQL, а не PHP)
Похоже, я сделал начало, с этого INNER JOIN skills AS s ON s.job_id = j.job_id
, который, я думаю, справится с поиском отдельного навыка, учитывая его ... имя? ... Id?
Полагаю, мой вопрос будет заключаться в том, как бы выглядел этот запрос, если бы, например, я хотел ограничить результаты для всех, кто работал в Microsoft OR Google
и имеет навыки Python AND C++
?
Если я получу пример для этого, я могу экстраполировать, но на данный момент я не уверен, хочу ли я больше INNER JOINs или предложений WHERE.
I think что я хочу расширить эту вторую последнюю строку AND sn.skill_id = s.skill_id
, разделив строку поиска навыков, в моем примере Python AND C++
и сгенерировав некоторые SQL по строкам AND (s.skill_id = X )
, где X - это идентификатор навыка для Python , НО Я не знаю, как обрабатывать Python AND C++
или что-то более сложное, например Python AND (C OR C++)
...
Обновить
Чтобы было ясно, пользователи технически подготовлены и ожидают, что смогут вводить сложные запросы. Например, для навыков: (C AND kernel)OR (C++ AND realtime) OR (Doors AND (UML OR QT))
.
Финальное обновление
Требования только что изменились. Человек, для которого я это кодирую, только что сказал мне, что если кандидат соответствует критериям поиска по навыкам на любой работе, на которой он когда-либо работал, то я должен вернуть ВСЕ вакансии для этого кандидата.
Мне это кажется нелогичным, но он клянется, что это то, чего он хочет. Я не уверен, что это можно сделать даже в одном запросе (я рассматриваю несколько запросов; сначала нужно получить кандидатов с соответствующими навыками, затем второй - получить все их рабочие места).