2015-12-21 142 views
0

我有一个函数,它接受一个类别的名称并返回与该类别关联的所有过滤器组以及与每个组关联的过滤器。 但是有太多的循环和查询进行,有没有办法改善下面的代码?带有太多循环的SQL查询

public function getCategoryFilters($category_id) { 

    // get category filter groups 
    $query = $this->app['db']->query("SELECT filter_group_id 
    FROM " . DB_PREFIX . "category_filter 
    WHERE category_id = '" . (int)$category_id . "' 
    "); 

    if($query->rows) : 
     foreach ($query->rows as $group) : 

      $filter_group_query = $this->app['db']->query(" 
      SELECT DISTINCT fg.filter_group_id, fgd.name, fg.sort_order 
      FROM " . DB_PREFIX . "filter_group fg 
      LEFT JOIN " . DB_PREFIX . "filter_group_description fgd ON (fg.filter_group_id = fgd.filter_group_id) 
      WHERE fg.filter_group_id = '" . $group['filter_group_id'] . "' 
      AND fgd.language_id = '1' 
      GROUP BY fg.filter_group_id 
      ORDER BY fg.sort_order, LCASE(fgd.name)"); 

      foreach ($filter_group_query->rows as $filter_group) : 
       $filter_data = array(); 

       $filter_query = $this->app['db']->query(" 
        SELECT DISTINCT f.filter_id, fd.name FROM " . DB_PREFIX . "filter f 
        LEFT JOIN " . DB_PREFIX . "filter_description fd ON (f.filter_id = fd.filter_id) 
        WHERE f.filter_group_id = '" . (int)$filter_group['filter_group_id'] . "' 
        AND fd.language_id = '1' 
        ORDER BY f.sort_order, LCASE(fd.name)"); 

       foreach ($filter_query->rows as $filter) : 
        $filter_data[] = array(
          'filter_id' => $filter['filter_id'], 
          'name'  => $filter['name'] 
        ); 
       endforeach; 

       if ($filter_data) : 
        $filter_group_data[] = array(
          'filter_group_id' => $filter_group['filter_group_id'], 
          'name'   => $filter_group['name'], 
          'filter'   => $filter_data 
        ); 
       endif; 

      endforeach; 

     endforeach; 

     return $filter_group_data; 

    endif; 
} 

回答

2

答案取决于你的意思是“提高”是什么。如果你想提高代码的可读性,并确保稍后有人能够理解它,那么你应该创建子函数,就像Matei Mihai在他的回答中所建议的那样。

我会做这样的(伪):

public function getCategoryFilters($category_id) { 
    //Declare subfunctions 
    //Get the data concerning group filters 
    private function getFilterGroupData($category_id) { 
     ... 
     mysqli query here 
     ... 
     $result = array(); 
     insert query results into $result using a loop 
     return $result; 
    } 

    //Get specific filter data 
    private function getFilterData($filter_group_id) { 
     ... 
     mysqli query here 
     ... 
     $result = array(); 
     insert query results into $result using a loop: 
     for ($i = 0, $i < $mysqli_query->num_rows; $i += 1) { 
      ... 
     //Add $filter_group_id right here as you seem to need it in the results: 
      $result[$i]['filter_group_id'] = $filter_group_id; 
     } 
     return $result; 
    } 

    //Get the data you need, populate an array with all the results 
    $filter_groups_data = getFilterGroupData($category_id); 
    $count = count($filter_groups_data); 
    $all_filters_data = array(); 
    for ($i = 0; $i < $count; $i += 1) { 
     $filter_data = getFilterData($filter_groups_data[$i]; 
     //Insert into final results 
     array_push($all_filters_data, $filter_data); 
    } 
    return $all_filters_data; 
} 

但是,如果你想减少查询的数量,而不是,你可以写一个更复杂的查询,做一个连接filter_group的,filter_group_description,过滤器和filter_description表格,然后循环遍历结果一次。

只有当脚本执行速度有问题时,才应该考虑这一点,因为查询的可读性会降低很多。基本上,只要进入:

SELECT ... FROM 
filter_group 
INNER JOIN filter_group_description ON filter_group_id 
INNER JOIN filter ON filter_group_id 
INNER JOIN filter_description ON filter_id 
WHERE ... 
ORDER BY ...; 

如果你走这条路线,不过,一定要发表评论描述查询是如何工作的SQL PHP脚本里面有若干个连接是出了名的难以调试和变化。

+0

我将实现这两​​种方法,并在执行时间方面看到两者之间的差异。如果第二个建议运行得更快,我将评论这些功能解决方案,并将其作为参考。非常感谢。 – user1709251

0

你可以为每个循环做一个方法。通过这样做这样你会增加可读性,并简化代码:

public function getCategoryFilters($category_id) {} 

public function getFilterData($filterGroupIds) {} 

// ..... 
+0

确实。但我正在寻找一些东西来改善这个查询的性能 – user1709251

1

您可以使用in子句来减少查询时间; 这样的:

foreach ($query->rows as $group) : 
    $filter_group_ids[] = $group['filter_group_id']; 
endforeach; 

     $filter_group_query = $this->app['db']->query(" 
     SELECT DISTINCT fg.filter_group_id, fgd.name, fg.sort_order 
     FROM " . DB_PREFIX . "filter_group fg 
     LEFT JOIN " . DB_PREFIX . "filter_group_description fgd ON (fg.filter_group_id = fgd.filter_group_id) 
     WHERE fg.filter_group_id IN ('" . implode("','",$filter_group_ids) . "') 
     AND fgd.language_id = '1' 
     GROUP BY fg.filter_group_id 
     ORDER BY fg.sort_order, LCASE(fgd.name)");