2013-12-02 2 views
0

У меня есть несколько сложный запрос (с использованием подзапроса) для базы данных выборов, где я пытаюсь получить количество голосов за конкретного кандидата за позицию.Комплексный запрос с повторяющимся параметром, не работающим в PHP PDO

Коллекторы для votes таблице: идентификатор (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 раза в запросе. Это, по-видимому, вызывает проблему в коде PDO PHP. Мой код выглядит следующим образом:

$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 
) 

где общее число поданных бюллетеней вместо массива для каждого кандидата contianing свое имя и число голосов (из общего). Однако, если я использую явно небезопасный $query2, который просто вставляет значение $position в строку запроса три раза, я получаю результаты, которые я хочу.

Что-то не так с моим PHP-кодом выше? Я делаю то, что невозможно в PDO (надеюсь, нет!)? Моя базовая база данных - MySQL 5.5.32. Я даже попытался заменить три именованных параметра на неназванные ? и передать массив array($position, $position, $position) в метод $STH->execute() без каких-либо больших успехов.

+0

См. ОБЪЕДИНЕНИЯ. Это не (или не обязательно) сложный запрос. – Strawberry

ответ

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."`"; 

Как вы можете видеть, что нет ничего, чтобы связать в ПДО с этим конкретным запросом. Вы используете 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'); 
+0

Извините, я так долго принял, но спасибо, это сработало отлично! Видимо, когда я думал, что делаю что-то небезопасное, я просто неправильно думал о проблеме! – Devin

Смежные вопросы