2016-12-09 42 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