PHP中的子查询

Posted

技术标签:

【中文标题】PHP中的子查询【英文标题】:Subquery in PHP 【发布时间】:2011-01-14 12:52:30 【问题描述】:

让我们用两个表格举一个简单的例子:

USERS (Id, Name, City)
PLAYERS (Id_Player, Number, Team)

而且我必须在循环中使用子选择进行查询,其中子选择始终相同,所以我想将其分成两个查询并将子选择放在循环之外。

我解释一下。 有效但未优化的方法:

for($i=0;$i<something;$i++)

    $res2=mysql_query("SELECT Team from PLAYERS WHERE Number=$i 
        AND Id_Player IN (SELECT Id FROM USERS WHERE City='London')");

我想做但没用的:

$res1=mysql_query("SELECT Id from USERS where City='London'");
for($i=0;$i<something;$i++)

    $res2=mysql_query("SELECT Team from PLAYERS WHERE Number=$i 
        AND Id_Player IN **$res1**");

谢谢!

【问题讨论】:

为什么要进行两个查询而不是一个?一个带有子选择的查询会比两个独立的查询更快。另外,您能告诉我们您遇到了什么错误吗? 【参考方案1】:

这样的事情应该可以工作。

<?
$sql = "SELECT Team from PLAYERS 
    JOIN USERS on (Id_player=Id)
    WHERE Number BETWEEN $minID AND $maxID
    AND City='London'
    GROUP BY Team";

$results=mysql_query($sql) or die(mysql_error());


// $results contain all the teams from London
// Use like normal..

echo "<ul>\n";

while($team = mysql_fetch_array($results))
    echo "\t<li>$team['Team']</li>\n";


echo "</ul>";

【讨论】:

【参考方案2】:

在循环中放置 SQL 查询可能会非常慢并且占用大量资源,请查看在您的 SQL 中使用 JOIN。这并不难,一旦你掌握了窍门,你就可以编写一些非常快速强大的 SQL。

这是一个很好的教程,值得一看,了解不同类型的 JOIN:http://www.keithjbrown.co.uk/vworks/mysql/mysql_p5.php

【讨论】:

一个非常好的主意。我的回答更多的是让 OP 使用JOIN;循环查询有时会很糟糕。【参考方案3】:

SELECT PLAYERS.*, USERS.City FROM PLAYERS, USERS WHERE USERS.City='London' AND PLAYERS.Number = $i

不是最好的方法;也许是LEFT JOIN,但它应该可以工作。不过可能语法错误。

詹姆斯

编辑

警告:这不是最理想的解决方案。请给我一个更具体的查询,我可以为您整理一个join 查询。

考虑到您的评论,让我们看另一个示例。这将使用 PHP 创建一个列表,我们可以使用 MySQL IN 关键字。

首先,进行查询:

$res1 = mysql_query("SELECT Id from USERS where City='London'");

然后,遍历您的查询并将每个 Id 字段一个接一个地放在逗号分隔的列表中:

$player_ids = ""; 而($row = mysql_fetch_array($res1)) $player_ids .= $row['Id'] 。 ","; $player_ids = rtrim($player_ids, ",");

您现在应该有一个这样的 ID 列表:

12, 14, 6, 4, 3, 15, ...

现在将其放入您的第二个查询中:

for($i = 0; $i

此处给出的示例可以针对其特定目的进行改进,但我会尽可能保持开放。

如果您想创建一个字符串列表,而不是 ID 或其他数字,请修改第一个 while 循环,将其中的行替换为

$player_ids .= "'" . $row['Id'] . "',";

如果您能给我您使用的实际查询,我可以想出更好的方法;正如我上面所说,这是一种更通用的做事方式,不一定是最好的。

【讨论】:

谢谢,但让我们假设 $res1 要复杂得多,并且与循环无关。那么它不会像你说的那样优化,对吧?因为它必须在每次迭代中评估“USERS.City='London'”。谢谢【参考方案4】:

在循环中运行查询不是一个好主意。更好的是获取整个表,然后循环遍历表。

所以查询会是这样的:

"SELECT Team from PLAYERS WHERE Number BETWEEN($id, $something) 
        AND Id_Player IN (SELECT Id FROM USERS WHERE City='London')"

【讨论】:

【参考方案5】:
$res1=mysql_query("SELECT Id from USERS where City='London'");
for($i=0;$i<something;$i++)

    $res2=mysql_query("SELECT Team from PLAYERS WHERE Number=$i 
        AND Id_Player IN **$res1**");

可以,但是mysql_query() 返回一个结果句柄。它不返回 id 值。任何选择查询,无论它返回多少行或多少行,都返回一个结果语句,而不是一个值。您首先必须使用 mysql_fetch...() 调用之一获取该行,该调用返回该行,然后您可以从中提取 id 值。所以...

$stmt = mysql_query("select ID ...");
if ($stmt === FALSE) 
    die(msyql_error());

if ($stmt->num_rows > 0) 
    $ids = array();
    while($row = mysql_fetch_assoc($stmt)) 
        $ids[] = $row['id']
    
    $ids = implode(',', $ids)
    $stmt = mysql_query("select TEAM from ... where Id_player IN ($ids)");
    .... more fetching/processing here ...

【讨论】:

以上是关于PHP中的子查询的主要内容,如果未能解决你的问题,请参考以下文章

是否可以使用 PHP+ODBC 发送包含带有内部连接的子查询的查询?

SELECT 中的子查询或 JOIN 中的子查询?

SQL中的子查询

如何在 mysql 或 php 中优化或加速我的子查询

MySQL基础语法之子链接查询和特殊查询(union 和 limit)

MySQL的子查询中FROM和EXISTS子句的使用教程