GROUP_CONCAT和LEFT_JOIN - 过滤记录

时间:2016-12-09 18:56:48

标签: mysql sql join concat

以下查询显示汤的列表,并为每个汤显示成分列表。

     //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 个答案:

答案 0 :(得分: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

答案 1 :(得分: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 

如果您想找到同时包含土豆和奶酪的食谱,您可以在in子句中添加奶酪并将值更改为= 2

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

这假定每种配方每种配料只列出一次。

由于你知道你正在寻找的成分,你可以动态地调整有相等的数量。