Как я могу написать подсчет SQL с предложением group by, используя Propel ORM в Symfony?
Вопрос
Как я могу написать следующий SQL-запрос, используя Propel ORM?
SELECT species, COUNT(*) FROM Bird GROUP BY species;
Нет правильного решения
Другие советы
Это не тот запрос, который привел бы к значимому гидратированному Bird
объекты, поскольку вы выбираете только species
столбец и количество этих видов.Так «сырой» SQL-запрос, как предложил Колин вероятно, лучший способ пойти сюда - но не увлажняйте в конце, просто получите данные из полученного результата PDOStatement
.
Если species
была ссылка на Species
table, вы можете работать оттуда:гидрат Species
объекты с дополнительным столбцом для подсчета птиц каждого вида.Если вы используете Symfony до версии 1.2, я настоятельно рекомендую Плагин DbFinder, так как это значительно упрощает работу с Criteria
, и имеет методы для выбора одного дополнительного столбца:
$speciesQuery = DbFinder::from('Species')->
join('Bird')->
groupBy('Bird.Id')->
withColumn('COUNT(Bird.Id)', 'NbBirds');
foreach ($speciesQuery->find() as $species) {
echo $species->getName() . ": " . $species->getNbBirds() . " birds\n";
}
Если вы используете Symfony 1.3 или 1.4, вам следует обновить Propel 1.4 в комплекте до Propel 1.5, куда Франсуа Заниотто, создатель DbFinder, перенес большую часть его функций и добавил больше, поэтому приведенный выше код работает в Propel 1.5 без дополнительного плагина.
$c = new Criteria(); $c->addAsColumn('cnt', "count(*)"); self::addSelectColumns($c); $c->addGroupByColumn(BirdPeer::SPECIES);
но вам нужно будет выполнить пользовательскую гидратацию, если вам нужно получить счетчик (*) для ваших заполненных объектов.
Мне было трудно найти хоть один документ по Propel Criteria (кажется, там нет документа API), поэтому я обычно использую список в Главе 8 книги symfony;но я понятия не имею, является ли это исчерпывающим.
Но что вы можете сделать, так это передать SQL напрямую в Propel.Следующее изменено из примера в http://propel.phpdb.org/docs/user_guide/chapters/FindingObjects.html:
$con = Propel::getConnection(DATABASE_NAME);
// if not using a driver that supports sub-selects
// you must do a cross join (left join w/ NULL)
$sql = "SELECT species, COUNT(*) FROM Bird GROUP BY species";
$stmt = $con->createStatement();
$rs = $stmt->executeQuery($sql, ResultSet::FETCHMODE_NUM);
return parent::populateObjects($rs);
Не думаю, что я когда-либо использовал это таким образом, хотя мог бы.