0

我在解决迭代 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

4 回答 4

4

在 sql 中进行连接会快得多

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

于 2011-07-26T01:18:10.420 回答
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

或三个(如果您有很多记录并且您担心"United States of America"通过从 MySQL 到应用程序代码的连接发送数十万次):

--- **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
于 2011-07-26T01:46:16.840 回答
0

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

于 2011-07-26T01:22:21.447 回答
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 号,您总是必须进行连接。使用代码和缩写,您通常可以只用代码或缩写来满足您的用户。)

于 2011-07-26T01:56:23.607 回答