Я застреваю при попытке получить данные через PHP из базы данных MySQL, когда в SQL-заявлении есть несколько ключевых слов. Мой опыт в основном заключается в интерфейсе, поэтому его борьба была довольно сложной.
У меня есть экран, где я хочу показать несколько навыков (это ключевые слова), все из которых извлекаются из одной таблицы в БД. Когда пользователь выбирает одно или несколько навыков и щелкает по ссылке, я хочу вернуть сопоставленные проекты для выбранных навыков, все с помощью правильного запроса бэкэнда (т.е. Другой вариант, который я должен был вернуть все данные во внешний интерфейс и использовать JS для фильтрации по желанию, но каким-то образом я в настоящее время не считаю это оптимальным для моего текущего сценария)
У меня есть таблица MySQL, называемая web_projects
которой перечислены несколько проектов с такими столбцами, как project_id
, project_name
т.д. И т.д.
В другой таблице, называемой web_skills
перечислены несколько навыков с такими столбцами, как skill_id
, skill_name
т.д. skill_name
т.д.
Поскольку существует взаимосвязь "многие-ко-многим" (каждый проект может иметь несколько навыков, и каждый навык может быть включен в несколько проектов) У меня есть третья таблица для управления этими отношениями. В этой таблице web_project_skills
есть 3 столбца id
, project_id
, skill_id
.
Визуальный вид с отображением:
[пожалуйста, не обращайте внимания на типы данных, его просто созданная таблица быстро и будет изменена позже]
Я отправляю данные из своего приложения через:
http://localhost/am/get.php?q=getprojectsforskill&skill=HTML5
и получить строку:
$q = trim($_GET["skill"]);
Следующий SQL (это исследование) помогает мне получить значения для этого запроса, и он отлично работает:
$st = "SELECT web_projects.*
FROM web_projects
JOIN web_project_skills
ON web_projects.project_id=web_project_skills.project_id
WHERE web_project_skills.skill_id =
(SELECT web_skills.skill_id
FROM web_skills
WHERE web_skills.skill_name = '".$q."'
)";
Теперь мой почтовый метод изменился, и я получаю строку, разделенную пробелами, например:
http://localhost/am/get.php?q=getprojectsforskill&skill=HTML5%2CCSS3
Мой запрос теперь включает:
$q = trim($_GET["skill"]);
$pieces = explode(",", $q);
$subQuery = "SELECT web_skills.skill_id
FROM web_skills
WHERE web_skills.skill_name = '$pieces[0]'";
if(count($pieces)>1){
for($i=1;$i<count($pieces);$i++){
$subQuery.=" OR web_skills.skill_name = '$pieces[$i]' ";
}
}
$st = "SELECT web_projects.*
FROM web_projects
JOIN web_project_skills
ON web_projects.project_id=web_project_skills.project_id
WHERE web_project_skills.skill_id = ($subQuery)";
Для запроса с одним значением он прекрасно работает, так как нет дополнения к заявлению SQL с помощью for
цикла.
Но для запроса с более чем одним я получаю ошибки. Пример URL (как указано выше):
http://localhost/am/get.php?q=getprojectsforskill&skill=HTML5%2CCSS3
Ошибки, которые я получаю с изменениями из 3-х переменных, я попытался в переменной subQuery:
$subQuery.=" OR web_skills.skill_name = '$pieces[$i]' ";
Вышеуказанный оператор возвращает ошибку: An Error occured! SQLSTATE[21000]: Cardinality violation: 1242 Subquery returns more than 1 row
An Error occured! SQLSTATE[21000]: Cardinality violation: 1242 Subquery returns more than 1 row
$subQuery.=" UNION WHERE web_skills.skill_name='$pieces[$i]' ";
Вышеуказанный оператор возвращает ошибку: An Error occured! SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE web_skills.skill_name='CSS3' )' at line 7
An Error occured! SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE web_skills.skill_name='CSS3' )' at line 7
$subQuery.=" AND web_skills.skill_name = '$pieces[$i]' ";
Вышеуказанный оператор возвращает пустой массив
Для этого вам не нужен подзапрос, вы можете просто добавить еще одно соединение.
SELECT web_projects.*
FROM web_projects
JOIN web_project_skills
ON web_projects.project_id=web_project_skills.project_id
JOIN web_skills
ON web_skills.skill_id=web_project_skills.skill_id
WHERE skill_name = '".$q."'
Это должно вернуть все проекты, связанные с данным навыком.
Основываясь на принятом ответе от @juakali92, любому, кто любопытно узнать, как я получил это для моего текущего сценария:
[Для запроса, такого как http://localhost/am/get.php? Q = getprojectsforskill & skill = HTML5% 2CCSS3]
$q = trim($_GET["skill"]);
$pieces = explode(",", $q);
$st= "SELECT DISTINCT web_projects.*
FROM web_projects
JOIN web_project_skills
ON web_projects.project_id=web_project_skills.project_id
JOIN web_skills
ON web_skills.skill_id=web_project_skills.skill_id
WHERE web_skills.skill_name = '$pieces[0]'";
if(count($pieces)>1){
for($i=1;$i<count($pieces);$i++){
$st.="OR skill_name = '".$pieces[$i]."'";
}
}
Я должен был сделать SELECT DISTINCT
так как я получал несколько результатов из таблиц. Я предполагаю, потому что у меня есть условие OR
и в таблицах есть несколько совпадений. AND
возвращает нулевые результаты с DISTINCT
или без него.
Примечание. Существуют проблемы безопасности, которые необходимо будет решать отдельно.
EDIT/UPDATE:
Без for
:
$q = trim($_GET["skill"]);
$pieces = explode(",", $q);
$pieces1 = "'" . implode("','", $pieces) . "'";
$st= "SELECT DISTINCT web_projects.*
FROM web_projects
JOIN web_project_skills
ON web_projects.project_id=web_project_skills.project_id
JOIN web_skills
ON web_skills.skill_id=web_project_skills.skill_id
WHERE web_skills.skill_name IN ($pieces1)";