嵌套循环和SQL查询;需要速度

时间:2011-07-26 01:12:11

标签: php mysql performance nested-loops nested-queries

我在使用迭代SQL查询(我需要取消)解决问题时遇到了问题,而我正试图找出替代方法。

另外;遗憾的是,AJAX并不适合

鉴于我有以下位置数据表:

Country
    country_id
    name

State
    state_id
    country_id
    name

City
    city_id
    state_id
    name

现在,我正在尝试拉所有数据,但它实际上非常小( 147个城市,分为64个州,分为2个国家)但是这是永远的,因为我在迭代循环:

// this is pseudo-code, but it gets the point across

$countries = getCountries();
foreach($countries as &$country){
    $country['states'] = $states = getStates($country['country_id']);
    foreach($states as &$state){
        $state['cities'] = getCities($state['state_id']);
    }
}

我之所以这样,是因为我的最终结果集需要采用以下形式:

$countries = array(
    array(
        'name' => 'country_name',
        'id' => 'country_id',
        'states' => array(
            array(
                'name' => 'state_name',
                'id' => 'state_id',
                'cities' => array(
                    array(
                        'name' => 'city_name',
                        'id' => 'city_id',
                    ),
                    // ... more cities
                ),
            ),
            // ... more states
        ),
    ),
    // ... more countries
);

我似乎无法绕过更快的方法。查询分层数据还有哪些替代方案?


修:

    $sql = "SELECT
                `dbc_country`.`name` as `country_name`,
                `dbc_state`.`name` as `state_name`,
                `city_id`,
                `dbc_city`.`name` as `city_name`,
                `latitude`,
                `longitude`
            FROM
                `dbc_city`
                    INNER JOIN
                `dbc_state` ON `dbc_city`.`state_id` = `dbc_state`.`state_id`
                    INNER JOIN
                `dbc_country` ON `dbc_state`.`country_id` = `dbc_country`.`country_id`";
    $locations = array();
    foreach($datasource->fetchSet($sql) as $row){
        $locations[$row['country_name']][$row['state_name']][] = array(
            $row['city_id'],
            $row['city_name'],
            $row['latitude'],
            $row['longitude'],
        );
    }

我还删除了州/国家/地区的id值,因为它们无用占用空间

4 个答案:

答案 0 :(得分:4)

在sql

中进行连接要快得多 然后

迭代单个(更大的)结果集。

答案 1 :(得分:1)

我会使用一个查询:

SELECT co.name AS CountryName
     , st.name AS StateName
     , ci.name AS CityName
FROM Country AS co
  LEFT JOIN State AS st
    ON st.country_id = co.country_id
  LEFT JOIN City AS ci
    ON ci.state_id = st.state_id
ORDER BY CountryName
       , StateName
       , CityName

或三(如果你有很多记录,你担心从MySQL到应用程序代码的连接上发送数次"United States of America"数次):

--- **GetCountries**
SELECT co.country_id
     , co.name AS CountryName
FROM Country AS co
ORDER BY CountryName

--- **GetStates**
SELECT co.country_id
     , st.state_id
     , st.name AS StateName
FROM Country AS co
  JOIN State AS st
    ON st.country_id = co.country_id
ORDER BY CountryName
       , StateName

--- **GetCities**
SELECT co.country_id
     , st.state_id
     , ci.city_id
     , ci.name AS CityName
FROM Country AS co
  JOIN State AS st
    ON st.country_id = co.country_id
  JOIN City AS ci
    ON ci.state_id = st.state_id
ORDER BY CountryName
       , StateName
       , CityName

答案 2 :(得分:0)

数据库设计的常用方法强调尽可能少地进行查询。它看起来正确。但是引用这个帖子标题“查询效率”,这种方法并不适用于MySQL。仅供参考,MySQL旨在非常有效地处理连接和断开连接,并且可以非常快速地响应小而简单的查询,因此只要您立即在序列查询中释放内存,我认为没关系。此外,如果您的记录增长(例如,进入100000条记录),那么您可能会三思而后行使用JOIN语句。

答案 3 :(得分:0)

如果你的数据看起来像这样呢?

Table: country 
iso_country_code        country_name
--
CA                      Canada
US                      United States of America

Table: state
iso_country_code    state_abbr    state_name
--
US                  NE            Nebraska
CA                  NB            New Brunswick

Table: city
iso_country_code    state_abbr    city_name
--
US                  NE            Lincoln
US                  NE            Arapahoe
CA                  NB            Dalhousie
CA                  NB            Miramichi

您是否可以使用代码和缩写而不是全名?

即使您不能,也可以使用单个SELECT语句获取所有必需的行,然后遍历行以填充数组。 (您也可以使用ID号进行此操作,但使用ID号,您始终必须进行连接。使用代码和缩写,您通常只需使用代码或缩写即可满足您的用户。)