Соединение MySQL INNER с правым соединением и несколькими условными предложениями WHERE с полным текстом

У меня есть три таблицы:

Meta
Posters
Tags

Плакаты имеют отношение один к одному на Meta. Теги имеют отношение один к одному на poster_id к авторам.

Meta <-- many-to-one Posters <-- many-to-one Tags

поэтому у мета-элемента может быть много постеров, а у постера может быть много тегов.

Я пытаюсь создать один запрос, который может принимать условные фильтры, включая конкретные Tag типы.

function get_filter_posters($filters, $start) {
$query = "SELECT Meta.id, Meta.year, Posters.id AS poster_id, Posters.filename, Meta.imp_title
FROM Meta INNER JOIN Posters ON Meta.id = Posters.movie_id
RIGHT JOIN Tags ON Posters.id = Tags.poster_id
WHERE Meta.year >= :lower
AND Meta.year <= :upper ";

foreach ($filters["genre"] as $key => $value) {
if($value){ $query .= " AND Meta.genre = '".$key."' "; }
}

foreach ($filters["style"] as $key => $value) {
if($value){ $query .= " AND Tags.tag = '".$key."' "; }
}

$query .= "ORDER BY Meta.year DESC
LIMIT :start,:limit";

$statement = $this->db->prepare($query);
$statement->bindParam(':limit', $this->limit, PDO::PARAM_INT);
$statement->bindParam(':start', $start, PDO::PARAM_INT);
$statement->bindParam(':lower', $filters["year_range"][0], PDO::PARAM_INT);
$statement->bindParam(':upper', $filters["year_range"][1], PDO::PARAM_INT);
$statement->execute();
return $statement->fetchAll(PDO::FETCH_ASSOC);
}

это работает только тогда, когда элемент стиля SINGLE имеет значение true. Если найдено более одного элемента стиля, и поэтому добавлено дополнительное условие where:

      foreach ($filters["style"] as $key => $value) {
if($value){ $query .= " AND Tags.tag = '".$key."' "; }
}

тогда запрос всегда возвращает пустой набор, если на самом деле существует один плакат с несколькими тегами.

если запрос написан только с одним элементом стиля, установленным в true, то запрос возвращает правильные постеры. Более одного ВСЕГДА возвращает пустое значение, что не так.

также это будет расширено с поиском ТЕКСТА. Это не работает, как ожидалось.

$query = "SELECT Meta.id, Meta.year, Posters.id AS poster_id, Posters.filename, Meta.imp_title,
MATCH(".$search_type.") AGAINST($term) AS Relevance
FROM Meta INNER JOIN Posters ON Meta.id = Posters.movie_id
RIGHT JOIN Tags ON Posters.id = Tags.poster_id
WHERE MATCH(".$search_type.")
AGAINST($term IN BOOLEAN MODE)";

foreach ($filters["genre"] as $key => $value) {
if($value){ $query .= " AND Meta.genre = '".$key."' "; }
}

foreach ($filters["style"] as $key => $value) {
if($value){ $query .= " AND Tags.tag = '".$key."' "; }
}

$query .= "AND Meta.year >= ".$filters["year_range"][0]."AND Meta.year <= ".$filters["year_range"][1]."ORDER BY Relevance + Meta.year DESC
LIMIT :start,:limit";

$statement = $this->db->prepare($query);
$statement->bindParam(':start', $start, PDO::PARAM_INT);
$statement->bindParam(':limit', $this->limit, PDO::PARAM_INT);
$statement->execute();
return $statement->fetchAll(PDO::FETCH_ASSOC);

игнорировать тот факт, что я не сделал bindParam фильтр лет — будет сделано

Может быть, я неправильно подхожу к этому? Если так, любой совет очень помог бы

БЛАГОДАРЮ ВАС!

1

Решение

Правильное объединение отменяется оператором where. Таким образом, если тег существует, без постеров или метаданных, он ИСКЛЮЧАЕТСЯ (по сути, правильное объединение рассматривается как ВНУТРЕННЕЕ СОЕДИНЕНИЕ). Чтобы исправить, вам нужно ограничить предложение where для мета-части соединения либо на уровне постеров, либо на теге right join …

возможно

  $query = "SELECT Meta.id, Meta.year, Posters.id AS poster_id, Posters.filename, Meta.imp_title
FROM Meta
INNER JOIN Posters ON Meta.id = Posters.movie_id
RIGHT JOIN Tags ON Posters.id = Tags.poster_id
ON Meta.year >= :lower
AND Meta.year <= :upper ";

или же

  $query = "SELECT Meta.id, Meta.year, Posters.id AS poster_id, Posters.filename, Meta.imp_title
FROM Meta INNER JOIN Posters
ON Meta.id = Posters.movie_id
AND Meta.year >= :lower
AND Meta.year <= :upper
RIGHT JOIN Tags ON Posters.id = Tags.poster_id";
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]