我对选举数据库有一些复杂的查询(使用子查询),我试图获得某个职位的每个特定候选人的投票数。
votes
表的标题是: id(PRIMARY KEY),时间戳,pos1,pos2,...,pos6 其中 pos1-pos6 是职位名称。投票选票成为此表中的新行,其中所选候选人的成员编号(候选人链接到数据库中“成员资格”表中的个人资料)存储为每个职位的值。因此,例如,数据库中的一行可能如下所示(除了实际的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()
方法,但没有取得更大的成功。
答案 0 :(得分:1)
您的查询并不复杂。我认为部分困惑在于您没有正确构建基本SQL。您试图将“总统”视为值和列。最终的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中没有任何内容可以与此特定查询绑定。您使用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');