self::STAT + поиск

Общие вопросы по использованию фреймворка. Если не знаете как что-то сделать и это про Yii, вам сюда.
Закрыто
che
Сообщения: 62
Зарегистрирован: 2011.09.11, 10:51
Откуда: Екатеринбург

self::STAT + поиск

Сообщение che »

Здравствуйте!
У меня много статистических запросов, по которым надо сделать поиск и сортировку.

Модель:

Код: Выделить всё

.............................
    public function relations()
    {
        return array(
            // статистические запросы
            'all_check_count'=>array(self::STAT, 'PlanObject', 'object_id'),
            'violation_check_count'=>array(self::STAT, 'PlanObject', 'object_id', 'condition'=>'violations_number>0'),
            'violation_count'=>array(self::STAT, 'PlanObject', 'object_id', 'select'=>'SUM(violations_number)'),
            'check_products_count'=>array(self::STAT, 'PlanObject', 'object_id', 'select'=>'SUM(number_products_tested)'),
            'reject_products_name_count'=>array(self::STAT, 'PlanObject', 'object_id', 'select'=>'SUM(protocols_number)'),
        );
    }

    public function search()
    {
        $criteria = new CDbCriteria;

        $criteria->with = array('plan_objects', 'all_check_count', 'violation_check_count', 'violation_count', 'check_products_count');

        $criteria->compare('name',$this->name,true);
        $criteria->compare('address',$this->address,true);
    
        return new CActiveDataProvider($this, array(
            'criteria'=>$criteria,
            'pagination'=>array(
                'pageSize'=>20,
            ),
        ));
    }
.............................
Как я понял по статистическим данным нельзя сделать поиск, это можно обойти при помощи джойнов, но полей может быть намного больше, есть ли другие варианты?
esche
Сообщения: 1054
Зарегистрирован: 2010.11.24, 03:39

Re: self::STAT + поиск

Сообщение esche »

che писал(а):Как я понял по статистическим данным нельзя сделать поиск, это можно обойти при помощи джойнов, но полей может быть намного больше, есть ли другие варианты?
Можно вычислять статистические данные непосредственно перед использованием (сортировкой?) и "складывать" их в дополнительное поле (этой или другой таблицы.. можно создавать временную, в памяти), либо вешать триггеры на изменение данных и опять же сохранять статистику в дополнительное поле.
...
che
Сообщения: 62
Зарегистрирован: 2011.09.11, 10:51
Откуда: Екатеринбург

Re: self::STAT + поиск

Сообщение che »

Нашел решение.
Модель:

Код: Выделить всё

class Object extends CActiveRecord
{
    // вычисляемые переменные
    public $acc;
    public $rpnc;

    .................................................    

    public function scopes()
    {
        return array(
            'all_check_count'=>array(
                'select'=>'count(pl_obj.id) as acc',
                'join'=>'LEFT JOIN '. PlanObject::tablename() .' pl_obj ON pl_obj.object_id = t.id',
                'group'=>'t.id',
            ),
            'reject_products_name_count'=>array(
                'select'=>'SUM(pl_obj.protocols_number) as rpnc',
                'join'=>'LEFT JOIN '. PlanObject::tablename() .' pl_obj ON pl_obj.object_id = t.id',
                'group'=>'t.id',
            ),
        );
    }

    public function rules()
    {
        return array(
            array('name, address, acc, rpnc', 'safe', 'on'=>'search'),
        );
    }

    public function search()
    {
        $criteria = new CDbCriteria;
        $criteria->select = 't.*';

        $criteria->scopes=array('all_check_count', 'reject_products_name_count');

        $criteria->compare('name',$this->name,true);
        $criteria->compare('address',$this->address,true);
        ($this->acc) ? $criteria->having = 'acc = '. $this->acc : '';
        ($this->rpnc) ? $criteria->having = 'rpnc = '. $this->rpnc : '';
        
        // сортировка
        $sort = new CSort(__CLASS__);
        $sort->attributes = array(
            'name'=>array(
                'asc'=>'t.name',
                'desc'=>'t.name desc',
            ),
            'address'=>array(
                'asc'=>'t.address',
                'desc'=>'t.address desc',
            ),
            'acc'=>array(
                'asc'=>'acc',
                'desc'=>'acc desc',
            ),
            'rpnc'=>array(
                'asc'=>'rpnc',
                'desc'=>'rpnc desc',
            ),
        );
        $sort->defaultOrder='t.id DESC';
        $sort->applyOrder($criteria);

        
        return new CActiveDataProvider(__CLASS__, array(
            'criteria'=>$criteria,
            'sort'=>$sort,
            'pagination'=>array(
                'pageSize'=>20,
            ),
        ));
    }    
}
Контроллер:

Код: Выделить всё

    public function actionObjects ()
    {
        $model = new Object('search');
        $model->unsetAttributes();

        if(isset($_GET['Object'])) {
            $model->attributes=$_GET['Object'];
        }

        if (isset($_GET['ajax']))
        {
            $this->renderPartial('objects_table',array(
                'model'=>$model,
            ));
        } else {
            $this->render('objects_table',array(
                'model'=>$model,
            ));
        }
    }
Представление:

Код: Выделить всё

$this->widget('zii.widgets.grid.CGridView', array(
    'dataProvider'=>$model->search(),
    'filter'=>$model,
    'ajaxUpdate'=>true,
    'summaryText'=>false,
    'selectableRows'=>0,
    'columns'=>array(
        'name',
        'address',
        'acc',
        'rpnc',
    ),
));
 
Конечно, это все те же джойны, но в данном случае они хранятся "отдельно" и при необходимости их еще раз писать не надо.
Закрыто