php - 具有重复参数的复杂查询在 PHP PDO 中不起作用

标签 php mysql pdo subquery

我对选举数据库有一个有点复杂的查询(使用子查询),我试图获取某个职位的每个特定候选人的票数。

votes 表的 header 为:id(主键)、时间戳、pos1、pos2、...、pos6,其中 pos1-pos6 是位置名称。投票将成为该表中的新行,所选候选人的成员 ID 号(候选人链接到数据库中“成员资格”表中的个人资料)作为每个职位的值。例如,数据库中的一行可能如下所示(除了实际的 6 个位置名称):

id    timestamp    pos1   pos2   pos3 (and so on)
=================================================
6     1386009129   345    162    207

我想使用 PHP PDO 获取每个职位的结果,列出每个职位的候选人姓名以及他们为此职位收到的票数。因此,原始数据库结果应显示为(以“pos1”为例):

name         votecount
======================
Joe Smith    27
Jane Doe     45

我有一个原始 SQL 查询,我可以成功地使用它来获取这些结果,该查询是(使 pos1 成为实际列/位置名称 President):

SELECT (SELECT fullname FROM membership memb WHERE member_id=`President`) name, count(`President`) votecount FROM `election_votes` votes GROUP BY `President`

如您所见,职位名称(此处是President)在查询中重复了 3 次。这似乎会导致 PHP PDO 代码出现问题。我的代码如下:

$position = "President";   // set in earlier code as part of a loop

$query = "SELECT (SELECT fullname FROM membership memb WHERE member_id=:pos1) name, count(:pos2) votecount FROM `election_votes` votes GROUP BY :pos3";
$query2 = "SELECT (SELECT fullname FROM membership memb WHERE member_id=$position) name, count($position) votecount FROM `election_votes` votes GROUP BY $position";  // NOT SAFE!

$STH = $DBH->prepare($query);
$STH->bindParam(':pos1', $position);
$STH->bindParam(':pos2', $position);
$STH->bindParam(':pos3', $position);
$STH->execute();

while($row = $STH->fetch(PDO::FETCH_ASSOC)) {
  print_r($row);
  // I'd like to do other things with these results
}

当我使用查询 $query 运行此命令时,我没有获得所需的每人结果。我的输出是:

Array
(
    [name] => 
    [votecount] => 47
)

其中 47 是投票总数,而不是每个候选人包含其姓名和票数的数组(总票数)。但是,如果我使用明显不安全的 $query2,它只是将 $position 的值插入查询字符串三次,我就得到了我想要的结果。

我上面的PHP代码有问题吗?我是否在做一些在 PDO 中不可能完成的事情(我希望不是!)?我的底层数据库是MySQL 5.5.32。我什至尝试将三个命名参数替换为 ? 未命名参数,并将数组 array($position, $position, $position) 传递到 $ STH->execute() 方法没有取得更大的成功。

最佳答案

您的查询并不复杂。我认为造成困惑的部分原因是您没有正确构建基本 SQL。您试图将“President”视为值和列。最终的 SQL 应该如下所示:

SELECT 
    `fullname` AS `name`, 
    COUNT(`id`) AS `votecount` 
FROM 
    `election_votes` AS `votes` 
LEFT JOIN 
    `membership` AS `memb` ON `member_id` = `president` 
GROUP BY 
    `pos1`

您加入election_votes表到membership表,其中列 pos1 中的值等于 member_id 列中的值.

注意:您不能在 PDO ( Can PHP PDO Statements accept the table or column name as parameter? ) 中使用带有表名和列名的参数,因此您必须手动转义这些参数。

/**
 *  Map positions/columns manually.  Never use user-submitted data for table/column names
 */
$positions = array('President' => 'pos1', 'Vice-president' => 'pos2');

$column = $positions['President'];

您应该能够在 PDO 中将查询重写为:

/**
 *  Get election results for all candidates
 */
$sql = "SELECT 
            `fullname` AS `name`, 
            COUNT(`id`) AS `votecount` 
        FROM 
            `election_votes` AS `votes` 
        LEFT JOIN 
            `membership` AS `memb` ON `member_id` = `".$column."` 
        GROUP BY 
            `".$column."`";

正如您所看到的,PDO 中没有任何内容可以与此特定查询绑定(bind)。您可以使用 BindParam 来过滤出现在 WHERE 子句中的值(同样:不是表/列名称)。例如:

/**
 *  Get election results for person named 'Homer Simpson'
 */
$sql = "SELECT 
            `fullname` AS `name`, 
            COUNT(`id`) AS `votecount` 
        FROM 
            `election_votes` AS `votes` 
        LEFT JOIN 
            `membership` AS `memb` ON `member_id` = `".$column."` 
        WHERE 
            `fullname` = :fullname:
        GROUP BY 
            `".$column."`";
$STH = $DBH->prepare($sql);
$STH->bindParam(':fullname', 'Homer Simpson');

关于php - 具有重复参数的复杂查询在 PHP PDO 中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20335643/

相关文章:

php - 通过 PayPal 和信用卡接收付款

php - 为什么 .post jquery 函数在我的代码中不起作用?

Mysql 查询 - 在 case 语句中使用 Locate 函数按来源对流量进行分组

php - 我是否应该以及如何将我的用户对象保存到 session 中?

php - 为什么PDO不显示任何结果?

php - 变量不会存储在 session 中

php - 在 WordPress 中显示日历

c# - 使用 C#、XAML 和 MySQL 进行基本身份验证

mysql - 当新的 WordPress 帖子添加到某个类别时捕获事件

php - PDO 两个相似的查询 - 仅第一个插入