6

有人告诉我,在循环中使用查询(选择)是一种不好的做法,因为它会降低服务器性能。

我有一个数组,例如

Array ( [1] => Los Angeles )
Array ( [2] =>New York)
Array ( [3] => Chicago )

这些只是 3 个索引。我使用的数组没有固定大小,所以有时它可以包含多达 20 个索引。

现在,我正在做的是(这不是所有的代码,而是基本的想法)

  1. 循环
  2. 查询服务器并选择所有住在“洛杉矶”的人的名字
  3. 把名字打印出来

输出将如下所示:

Los Angeles
      Michael Stern
      David Bloomer
      William Rod

New York
      Kary Mills

Chicago
      Henry Davidson
      Ellie Spears

我知道这是一种非常低效的方法,因为随着表格稍后变大,它可能会产生很多查询。

所以我的问题是,有没有更好、更有效的方法来根据数组中的内容来选择信息,该数组可以是任何大小?

4

4 回答 4

5

使用IN查询,它将在单个查询中获取所有结果:

SELECT * FROM people WHERE town IN('LA', 'London', 'Paris')
于 2012-11-30T10:23:54.363 回答
4

要进一步添加到 MrCodes 答案,如果您从数组开始:-

$Cities = array(1=>'Los Angeles', 2=>'New York', 3=>'Chicago');
$query = "SELECT town, personname FROM people WHERE town IN('".implode("','", $Cities)."') ORDER BY town";
if ($sql = $mysqliconnection->prepare($query)) 
{
    $sql->execute();
    $result = $sql->get_result();
    $PrevCity = '';
    while ($row = $result->fetch_assoc()) 
    {
        if ($row['town'] != $PrevCity)
        {
            echo $row['town']."<br />";
            $PrevCity = $row['town'];
        }
        echo $row['personname']."<br />";
    }
}

作为数据库设计问题,您可能应该将城镇名称放在一个单独的表中,并且该人的表包含城镇的 id 而不是实际的城镇名称(使验证更容易、更快并且验证不太可能丢失记录因为有人打错了他们的家乡)

于 2012-11-30T10:27:42.403 回答
1

正如@MrCode 提到的那样,您可以使用 MySQL 的IN()运算符一次性获取所有所需城市的记录,但是如果您主要按城市对结果进行排序,您可以遍历结果集,跟踪最后看到的城市并输出新的初次遇到时的城市。

使用PDO和 MySQL 的FIELD()函数来确保结果集与原始数组的顺序相同(如果您不关心这一点,您可以简单地执行ORDER BY city,这会更有效,尤其是在使用合适的索引时列city):

$arr = ['Los Angeles', 'New York', 'Chicago'];
$placeholders = rtrim(str_repeat('?, ', count($arr)), ', ');

$dbh = new PDO("mysql:dbname=$dbname", $username, $password);
$qry = $dbh->prepare("
  SELECT   city, name
  FROM     my_table
  WHERE    city IN ($placeholders)
  ORDER BY FIELD(city, $placeholders)
");

if ($qry->execute(array_merge($arr, $arr))) {

  // output headers
  echo '<ul>';

  $row = $qry->fetch();
  while ($row) {
    $current_city = $row['city'];

    // output $current_city initialisation
    echo '<li>'.htmlentities($current_city).'</li><ul>';
    do {
      // output name $row
      echo '<li>'.htmlentities($row['name']).'</li>';
    } while ($row = $qry->fetch() and $row['city'] == $current_city);
    // output $current_city termination
    echo '</ul>';
  }

  // output footers
  echo '</ul>';
}
于 2012-11-30T10:24:39.050 回答
0

这就是准备好的陈述的目的。您将占位符绑定到一个值,并像变量一样使用它,使用相同的查询。由于查询没有更改,因此您可以最大限度地减少与 mysql 服务器的通信,从而提高效率。

使用 PDO 的示例:

$cities = array(
    "Los Angeles",
    "New York",
    "Chicago"
);

try {
    //Change database parameters here (user, pass, database name)
    $db = new PDO("mysql:host=localhost;dbname=users", "user", "pass");
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

    $stmt = $db->prepare("SELECT * FROM `users` WHERE `city` = :city");

    foreach ($cities as $city) {
        $stmt->bindValue(":city", $city);
        $stmt->execute();

        $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
        //Output data here. You can format it however you'd like
        var_dump($city, $result);
    }

}
catch (PDOException $e) {
    //Error handling here
}
于 2012-11-30T10:23:30.510 回答