2016-12-09 2 views
0

Следующий запрос отображает список супов и для каждого супа список ингредиентов.GROUP_CONCAT и LEFT_JOIN - записи фильтра

 //Query only for demonstration 

    SELECT a.id_soup, a.soup,  
    GROUP_CONCAT(DISTINCT b.id_vegetables) AS vegetables_id, 
    GROUP_CONCAT(DISTINCT b.vegetables) AS vegetables_list 
    FROM soups a 
    LEFT JOIN ingredients ing ON a.soup = ing.soup_id 
    LEFT JOIN vegetables b ON b.id_vegetables = ing.list_vegetables 
    GROUP BY a.id_soup 

Я хочу, чтобы фильтровать записи, так что отображаются только те, в которых суп имеет определенный ингредиент (например, картофель). Что-то вроде:

 SELECT a.id_soup, a.soup,  
    GROUP_CONCAT(DISTINCT b.id_vegetables) AS vegetables_id, 
    GROUP_CONCAT(DISTINCT b.vegetables) AS vegetables_list 
    FROM soups a 
    LEFT JOIN ingredients ing ON a.soup = ing.soup_id 
    LEFT JOIN vegetables b ON b.id_vegetables = ing.list_vegetables 

    AND ing.list_vegetables LIKE "potatoes" 

    GROUP BY a.id_soup 

Эти запроса не фильтрует записи, но список ингредиентов больше не отображает все ингредиенты супа, только отображая ингредиент картофель.

Каков наилучший способ сделать это правильно?

Редакция:

с несколькими условиями - PHP и SQL:

$typesQuery = ""; 
    $bind=array(); 

    sqlQuery = "SELECT a.id_soup, a.soup, a.restaurant,  
    GROUP_CONCAT(DISTINCT b.id_vegetables) AS vegetables_id, 
    GROUP_CONCAT(DISTINCT b.vegetables) AS vegetables_list 
    FROM soups a 
    LEFT JOIN ingredients ing ON a.soup = ing.soup_id 
    LEFT JOIN vegetables b ON b.id_vegetables = ing.list_vegetables "; 

if($restaurant) { 
    $sqlQuery .= " AND a.restaurant LIKE ? "; 
    $typesQuery .= "s" ; 
    $bind[] = $restaurant; 
} 


if($vegetables) { 
    $sqlQuery .= " AND ... "; 
    $typesQuery .= "s" ; 
    $bind[] = $vegetables; 
} 

//EDITED: 
$vegetables = 'potatoes'; 
if($vegetables) { 
    $sqlQuery .= " HAVING SUM(CASE WHEN b.vegetables IN (?) THEN 1 ELSE 0 END) = 1 "; 
    $typesQuery .= "s" ; 
    $bind[] = $vegetables; 
} 


$sqlQuery .= " GROUP BY a.id_soup LIMIT ?,? "; 

if ($statementQuery = $conexion->prepare($sqlQuery)){ 

    $typesTotal = $typesQuery; 
    $bindTotal = array_merge(array(), $bind); 

    $typesQuery .= "ii"; 
    $bind[] = $start; 
    $bind[] = $limit; 
    array_unshift($bind, $typesQuery); 
    call_user_func_array( array($statementQuery, 'bind_param'), makeValuesReferenced($bind)); 

}else{ 
    $error = $conexion->error; 
    $success = false; 
    break; 
} 
    ... 

ответ

2

Используйте FIND_IN_SET после получения списка овощей.

SELECT * FROM (
SELECT a.id_soup, 
GROUP_CONCAT(DISTINCT b.id_vegetables) AS vegetables_id, 
GROUP_CONCAT(DISTINCT b.vegetables) AS vegetables_list 
FROM soups a 
LEFT JOIN ingredients ing ON a.soup = ing.soup_id 
LEFT JOIN vegetables b ON b.id_vegetables = ing.list_vegetables 
GROUP BY a.id_soup 
) X 
WHERE FIND_IN_SET('POTATOES',VEGETABLES_LIST) > 0 
+0

Я тестировал ваше решение на простом примере моего сообщения, и он отлично работает. Однако я не мог обратиться к моему реальному делу, потому что он фильтруется с несколькими условиями. Я редактировал свой пост. Спасибо заранее, если у вас есть еще предложения. – josei

1

Возможно, только условное предложение?

SELECT a.id_soup, a.soup,  
GROUP_CONCAT(DISTINCT b.id_vegetables) AS vegetables_id, 
GROUP_CONCAT(DISTINCT b.vegetables) AS vegetables_list 

FROM soups a 
LEFT JOIN ingredients ing ON a.soup = ing.soup_id 
LEFT JOIN vegetables b ON b.id_vegetables = ing.list_vegetables 
GROUP BY a.id_soup 
HAVING sum(case when b.vegetables in ('potatoes') then 1 else 0 end) = 1 

Если вы хотите, чтобы найти рецепты, которые имели как картофель и сыр можно добавить сыр к в п и изменить значение будет = 2

HAVING sum(case when b.vegetables in ('potatoes','cheese') then 1 else 0 end) = 2

Это предполагает, каждый ингредиент будет только перечисляться один раз в рецепте.

Поскольку вы знаете ингредиенты, которые ищете, вы можете динамически корректировать счет равенства в наличии.

+0

Я тестировал ваше решение на простом примере моего сообщения, и он отлично работает. Я отредактировал свой пост с несколькими условиями. Спасибо заранее, если у вас есть еще предложения. – josei

+0

Я не вижу проблемы, если «картофель» и «1» сверху становятся связанными параметрами, «картофель» может быть «картофелем», «цыпленком», «свининой», а второй параметр - '3' (количество 3 элементов в массиве) – xQbert

+0

Спасибо xQbert. Я редактирую свой пост. Мне нравится ваше решение, но мне все еще не удалось заставить его работать в моем случае. Я также попытался поместить эту часть запроса после GROUP BY, но это также не сработало. Я делаю несколько тестов, пытаясь понять, что происходит. – josei

Смежные вопросы