CGridView фильтрация с агрегатными (группирующими) функциями - например, MAX () - PullRequest
3 голосов
/ 16 ноября 2011

У меня есть CGridView, который использует столбец MAX() mysql для предоставления данных для одного из столбцов.У меня есть такая работа с сортировкой, но я не могу понять фильтрацию.Я предполагал, что мог бы просто использовать CDbCriteria::compare() call, чтобы установить его, но он не работает.Идеи?

Моя функция поиска:

    $criteria = new CDbCriteria;
    $criteria->condition = 't.is_deleted = 0 and is_admin = 0';
    // get last note date
    $criteria->select = array('t.*', 'MAX(n.visit_date) AS last_note');
    $criteria->join = 'LEFT JOIN notes n ON t.id = n.distributor_id';
    $criteria->group = 't.id';
    $criteria->order = 't.status';

    $criteria->compare('t.type', $this->type);
    $criteria->compare('t.name', $this->name, true);
    $criteria->compare('t.city', $this->city, true);
    $criteria->compare('t.state', $this->state);
    $criteria->compare('last_note', $this->last_note);



    return new CActiveDataProvider('Distributor', array(
            'criteria' => $criteria,
            'pagination' => array(
                'pageSize' => 20
            ),
            'sort' => array(
                'defaultOrder' => 'name',
                'attributes' => array(
                    'last_note' => array(
                        'asc' => 'last_note',
                        'desc' => 'last_note DESC'
                    ),
                )
            ),
        ));

На мой взгляд, у меня просто установлены значения имени и значения.

Я получаю ошибку CDbCommand failed to execute the SQL statement: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'last_note' in 'where clause'

Редактировать: Единственный способ, который я нашел для этого - это (потому что вы не можете иметь агрегатные функции в выражениях where), это проверить массив $_GET для значения last_note и добавить предложение has.Обратите внимание, что это не параметризовано или что-то еще, я просто хотел сделать это, чтобы посмотреть, будет ли это работать:

if(isset($_GET['Distributor']['last_note']) && $_GET['Distributor']['last_note'] != '') {
        $criteria->having = 'MAX(n.visit_date)=\'' . $this->last_note . "'";
}

Я ненавижу использовать переменные запроса в модели, как это, но этоя еще ничего не мог сделать.

Ответы [ 2 ]

3 голосов
/ 16 ноября 2011

Вы на правильном пути.Вы фильтруете агрегатные функции, такие как MAX() и SUM(), используя having.В запросе, подобном этому, вам, вероятно, следует добавить group, в противном случае в результате вы получите много дублированных данных, когда у дистрибьютора несколько заметок в один и тот же день (предполагается, что t.id является первичным ключом),Во-вторых, вы должны использовать именованные параметры вместо помещения переменных непосредственно в SQL.Таким образом, вместо compare('last_note'... вы получите что-то вроде этого:

$criteria->group = 't.id';
$criteria->having = 'MAX(n.visit_date) = :last_note';
$criteria->params = array(':last_note' => $this->last_note);
2 голосов
/ 16 ноября 2011

Чтобы фильтрация работала, у вас должен быть атрибут класса для хранения данных:

public $ last_note;

в противном случае $ this-> last_note ничего не будет возвращать, а ваши критерии $> сравнивать ('last_note', $ this-> last_note);

тоже ничего не сделает
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...