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