CakePHP: Как я могу использовать операцию "HAVING" при построении запросов с помощью метода find?
Я пытаюсь использовать предложение "HAVING" в запросе SQL, используя метод CakePHP paginate().
После некоторого поиска вокруг это выглядит так, что этого не может быть достигнуто с помощью методов pake cake()/find().
Код, который у меня есть, выглядит примерно так:
$this->paginate = array(
'fields' => $fields,
'conditions' => $conditions,
'recursive' => 1,
'limit' => 10,
'order' => $order,
'group' => 'Venue.id');
Одно из полей $- это псевдоним "расстояние". Я хочу добавить запрос, когда расстояние < 25 (например, расстояние H < 25).
Я видел два обходных пути до сих пор, к сожалению, не отвечаю моим потребностям. Два из них я видел:
1) Добавление предложения HAVING в опции "группа". например 'group' => 'Venue.id HAVING distance < 25'
. Похоже, что это не работает при использовании в сочетании с разбиением на страницы, поскольку оно испортит начальный запрос подсчета. (т.е. пытается SELECT distinct(Venue.id HAVING distance < 25)
, который явно недействителен.
2) Добавление предложения HAVING после условия WHERE (например, WHERE 1 = 1 HAVING field > 25
). Это не работает, так как кажется, что предложение HAVING должно появиться после оператора группы, который Cake размещает после WHERE в запросе, который он генерирует.
Кто-нибудь знает способ сделать это с помощью метода find() CakePHP? Я не хочу использовать query(), поскольку это потребует много переделок, а также означает, что мне нужно будет реализовать свою собственную логику разбиения на страницы!
Заранее спасибо
Ответы
Ответ 1
Вы должны положить это с условиями группы. как это
$this->find('all', array(
'conditions' => array(
'Post.length >=' => 100
),
'fields' => array(
'Author.id', 'COUNT(*) as Total'
),
'group' => array(
'Total HAVING Total > 10'
)
));
Надеюсь, это поможет вам
Ответ 2
Я использовал следующий трюк, чтобы добавить мое собственное предложение HAVING в конце предложения WHERE. Метод "dbo- > expression()" упоминается в документации подзапроса.
function addHaving(array $existingConditions, $havingClause) {
$model = 'User';
$db = $this->$model->getDataSource();
// Two fun things at play here,
// 1 - mysql doesn't allow you to use aliases in WHERE clause
// 2 - Cake doesn't allow a HAVING clause separate from a GROUP BY
// This expression should go last in the WHERE clause (following the last AND)
$taut = count($existingConditions) > 0 ? '1 = 1' : '';
$having = $db->expression("$taut HAVING $havingClause");
$existingConditions[] = $having;
return $existingConditions;
}
Ответ 3
Просто такая же проблема. Я знаю, что не нужно изменять внутренний код, но если вы откроете PaginatorComponent
и вы измените строку 188:
$count = $object->find('count', array_merge($parameters, $extra));
:
$count = $object->find(
'count',
array_merge(array("fields" => $fields),$parameters, $extra)
);
Все будет исправлено. Вы сможете добавить предложение HAVING в "группу", а COUNT (*) не будет проблемой.
Или сделайте строку:
$count = $object->paginateCount($conditions, $recursive, $extra);
включить $fields
:
$count = $object->paginateCount($fields,$conditions, $recursive, $extra);
После этого вы можете "переопределить" метод на модели и не забудьте включить поля $в find() и что это!, = P
Ответ 4
Вот еще одна идея, которая не решает проблему с разбивкой по страницам, но она чистая, поскольку она просто отменяет команду find в AppModel. Просто добавьте группу и добавьте элемент к вашему запросу, и это преобразуется в предложение HAVING.
public function find($type = 'first', $query = array()) {
if (!empty($query['having']) && is_array($query['having']) && !empty($query['group'])) {
if ($type == 'all') {
if (!is_array($query['group'])) {
$query['group'] = array($query['group']);
}
$ds = $this->getDataSource();
$having = $ds->conditions($query['having'], true, false);
$query['group'][count($query['group']) - 1] .= " HAVING $having";
CakeLog::write('debug', 'Model->find: out query=' . print_r($query, true));
} else {
unset($query['having']);
}
}
return parent::find($type, $query);
}
Найденный здесь
https://groups.google.com/forum/?fromgroups=#!topic/tickets-cakephp/EYFxihwb55I