2015-12-21 141 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)");