SQL для возврата значений из отношения «многие ко многим»

0

Я застреваю при попытке получить данные через 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.

Визуальный вид с отображением:

Изображение 174551

[пожалуйста, не обращайте внимания на типы данных, его просто созданная таблица быстро и будет изменена позже]

Я отправляю данные из своего приложения через:

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]' ";

Вышеуказанный оператор возвращает пустой массив

  • 0
    Почему в таблице web_skills есть столбец project_id?
  • 0
    @NineBerry Это столбец, который нужно удалить - он будет удален позже во время сеанса рефакторинга (есть много проблем, но я просто хочу начать работу с функциональностью, прежде чем перейти к рефакторингу). Я создал колонку во время моего первоначального усилия, где я думал, что отношения один ко многим будет достаточно.
Теги:

2 ответа

1
Лучший ответ

Для этого вам не нужен подзапрос, вы можете просто добавить еще одно соединение.

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."'

Это должно вернуть все проекты, связанные с данным навыком.

  • 1
    Использование $ q без экранирования специальных символов позволяет вводить sql ...
  • 0
    Я знаю об этом. Я просто давал ответ на его вопрос
Показать ещё 2 комментария
0

Основываясь на принятом ответе от @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)";

Ещё вопросы

Сообщество Overcoder
Наверх
Меню