【问题标题】:How to use this SQL in CDbCriteria如何在 CDbCriteria 中使用此 SQL
【发布时间】:2016-03-24 09:31:28
【问题描述】:

我目前有这个 SQL

 SELECT


       MAX(CASE WHEN uv.user_type_variables_id = 1 THEN uv.value ELSE NULL END) Question1,
       MAX(CASE WHEN uv.user_type_variables_id = 2 THEN uv.value ELSE NULL END) Question2,
       MAX(CASE WHEN uv.user_type_variables_id = 3 THEN uv.value ELSE NULL END) Question3,
       MAX(CASE WHEN uv.user_type_variables_id = 4 THEN uv.value ELSE NULL END) Question4,
       MAX(CASE WHEN uv.user_type_variables_id = 5 THEN uv.value ELSE NULL END) Question5,
       MAX(CASE WHEN uv.user_type_variables_id = 6 THEN uv.value ELSE NULL END) Question6

       FROM tbl_event_attendees AS ea

       LEFT JOIN tbl_user AS u ON ea.user_id = u.id
       LEFT JOIN tbl_event AS e ON ea.event_id = e.id                  
       LEFT JOIN tbl_user_variables AS uv on u.id = uv.user_id

       GROUP BY ea.id

我需要将它放入我现有的 CDbCriteria + 扩展关系。我需要将每个问题 1 到 6 作为一个变量,我可以用来放入 cgridview 中,但我正在努力让它工作。如果我使用 CSQLdataprovider,它可以正常工作,但我需要现有的标准。

我目前的标准

  public function search() {
        // Warning: Please modify the following code to remove attributes that
        // should not be searched.

        $criteria = new CDbCriteria;

        $criteria->compare('id', $this->id, true);
        $criteria->compare('event_id', $this->event_id, true);
        $criteria->compare('status_id', $this->status_id, true);
        $criteria->compare('checkin_status_id', $this->checkin_status_id, true);
//        $criteria->compare('guest_invites', $this->guest_invites, true);
        $criteria->compare('guest_of_user_id', $this->guest_of_user_id, true);
        $criteria->compare('user_id', $this->user_id, true);
        $criteria->compare('assign_group', $this->assign_group, true);

//        $criteria->with = 'eventAttendeesGroup';
        $criteria->with = 'user';
        $criteria->compare('user.forename', $this->user_forename, true);
        $criteria->compare('user.surname', $this->user_surname, true);
        $criteria->compare('user.company', $this->user_company, true);
        $criteria->compare('user.telephone', $this->user_telephone, true);
        $criteria->compare('user.dob', $this->user_dateofbirth, true);

        //need to get rid of this
        $criteria->compare('userVariables.value', $this->userType_value, true);

        $criteria->order = 'user.surname ASC';

        return new CActiveDataProvider($this, array(
            'criteria' => $criteria,
            //manages the pagination and how many users appear on the onsite reg page 
            'pagination'=>array('pageSize'=>50),
            //'pagination'=>false,
        ));
    }

有人有什么想法吗?

我想我必须为每个问题设置变量,并将它们添加到 usertype.variable 和 $this->variable 之类的关系中,但完全失败了。

编辑。

我可以得到

     function newsearch(){
     $rawData=Yii::app()->db->createCommand('SELECT


                    MAX(CASE WHEN uv.user_type_variables_id = 1 THEN uv.value ELSE NULL END) Question1,
                    MAX(CASE WHEN uv.user_type_variables_id = 2 THEN uv.value ELSE NULL END) Question2,
                    MAX(CASE WHEN uv.user_type_variables_id = 3 THEN uv.value ELSE NULL END) Question3,
                    MAX(CASE WHEN uv.user_type_variables_id = 4 THEN uv.value ELSE NULL END) Question4,
                    MAX(CASE WHEN uv.user_type_variables_id = 5 THEN uv.value ELSE NULL END) Question5,
                    MAX(CASE WHEN uv.user_type_variables_id = 6 THEN uv.value ELSE NULL END) Question6

                    FROM tbl_event_attendees AS ea

                    LEFT JOIN tbl_user AS u ON ea.user_id = u.id
                    LEFT JOIN tbl_event AS e ON ea.event_id = e.id                  
                    LEFT JOIN tbl_user_variables AS uv on u.id = uv.user_id

                    GROUP BY ea.id')->queryAll();
// or using: $rawData=User::model()->findAll();
return  $dataProvider=new CArrayDataProvider($rawData, array(
    'id'=>'Questions',
    'sort'=>array(
        'attributes'=>array(
             'Question1', 'Question2', 'Question3',
        ),
    ),
    'pagination'=>array(
        'pageSize'=>10,
    ),
));

在网格中显示 sql,但我仍然无法访问我的模型数据。

【问题讨论】:

  • 你真的想使用 CDbCriteria,可以实现它,但使用 CDbCommand 和编写自定义查询,并使用 CArrayDataProvider 可能更容易
  • 因为这是一个我继承的项目,所以对这个功能的依赖太多了。我考虑过将两个数据提供者作为一个数组添加和连接在一起,但我无法得到我想要的结果,因为在使用搜索/导出时,模型中的 sql 数据和数据根本没有链接,这是最后的游戏数据。
  • 好的,我已经添加了答案,如果有帮助,请告诉我。
  • 我会试一试。我已将 sql 添加到 cArraydataprovider 并且 sql 正常工作,您知道将模型数据也添加到数组的任何资源,所以我知道下次如何正确执行吗?
  • 那么您想将整个模型添加到查询的结果集中吗?如果你不想的话,你可以向数组中添加任何东西,如果这就是你的意思,这对 CArrayprovider 来说不是问题

标签: php sql yii


【解决方案1】:

我建议你创建一个MYSQL database view 并在 Yii 模型中使用它。通过这种方法,您可以像使用任何其他基于表的模型(INSERT,UPDATE,DELETE 操作除外)一样使用所有 Yii 模型功能,从而保留原始查询和条件的现有功能:

CREATE OR REPLACE VIEW myviewname AS 
... your SQL ...

MYSQL database view 创建后,make sure to create Yii model 用于您的数据库视图。在此模型中,使用您现有的自定义 search()。最后在您的程序中随意使用它,例如在 CGridView、报告等中。

【讨论】:

    【解决方案2】:

    我还没有彻底测试过。但是您需要将属性添加到模型类并将查询选择语句添加到 CDbCriteria (select) 属性并使用 together 属性以便立即执行查询。

    我假设这是 tbl_event_attendees 模型,如果使用得当,Yii 会自动填充记录

    class tblEventAttendees  extends CActiveRecord { 
    
    public $Question1;
    public $Question2;
    public $Question3;
    public $Question4;
    public $Question5;
    public $Question6;
    
    ...
    
    
        public function search() {
            // Warning: Please modify the following code to remove attributes that
            // should not be searched.
    
            $criteria = new CDbCriteria;
            $criteria->select = [
                't.*',
                'user.*',
                'MAX(CASE WHEN uv.user_type_variables_id = 1 THEN uv.value ELSE NULL END) Question1',
                'MAX(CASE WHEN uv.user_type_variables_id = 2 THEN uv.value ELSE NULL END) Question2',
                'MAX(CASE WHEN uv.user_type_variables_id = 3 THEN uv.value ELSE NULL END) Question3',
                'MAX(CASE WHEN uv.user_type_variables_id = 4 THEN uv.value ELSE NULL END) Question4',
                'MAX(CASE WHEN uv.user_type_variables_id = 5 THEN uv.value ELSE NULL END) Question5',
                'MAX(CASE WHEN uv.user_type_variables_id = 6 THEN uv.value ELSE NULL END) Question6',
                // add what you need
            ];
    
            $criteria->compare('id', $this->id, true);
            $criteria->compare('event_id', $this->event_id, true);
            $criteria->compare('status_id', $this->status_id, true);
            $criteria->compare('checkin_status_id', $this->checkin_status_id, true);
    //        $criteria->compare('guest_invites', $this->guest_invites, true);
            $criteria->compare('guest_of_user_id', $this->guest_of_user_id, true);
            $criteria->compare('user_id', $this->user_id, true);
            $criteria->compare('assign_group', $this->assign_group, true);
    
    //        $criteria->with = 'eventAttendeesGroup';
            $criteria->compare('user.forename', $this->user_forename, true);
            $criteria->compare('user.surname', $this->user_surname, true);
            $criteria->compare('user.company', $this->user_company, true);
            $criteria->compare('user.telephone', $this->user_telephone, true);
            $criteria->compare('user.dob', $this->user_dateofbirth, true);
    
            //need to get rid of this
            $criteria->compare('userVariables.value', $this->userType_value, true);
    
            $criteria->order = 'user.surname ASC';
    
            $criteria->with = array('user','event','userVariables');
            $criteria->together = true;
    
            return new CActiveDataProvider($this, array(
                'criteria' => $criteria,
                //manages the pagination and how many users appear on the onsite reg page
                'pagination'=>array('pageSize'=>50),
                //'pagination'=>false,
            ));
        }
    

    更新

    经过一些测试,我们发现问题不在于查询,而在于别名的使用。 Yii 使用别名映射查询结果,别名是使用 preg_match 函数从查询中提取的,参见https://github.com/yiisoft/yii/blob/1.1.17/framework/db/ar/CActiveFinder.php#L954

    所以改变这个

    $criteria->select = [
        't.*',
        'user.*',
        'MAX(CASE WHEN uv.user_type_variables_id = 1 THEN uv.value ELSE NULL END) Question1',
        'MAX(CASE WHEN uv.user_type_variables_id = 2 THEN uv.value ELSE NULL END) Question2',
        'MAX(CASE WHEN uv.user_type_variables_id = 3 THEN uv.value ELSE NULL END) Question3',
        'MAX(CASE WHEN uv.user_type_variables_id = 4 THEN uv.value ELSE NULL END) Question4',
        'MAX(CASE WHEN uv.user_type_variables_id = 5 THEN uv.value ELSE NULL END) Question5',
        'MAX(CASE WHEN uv.user_type_variables_id = 6 THEN uv.value ELSE NULL END) Question6',
        // add what you need
    ];
    

    这样就解决了问题

    $criteria->select = [
        't.*',
        'user.*',
        'MAX(CASE WHEN uv.user_type_variables_id = 1 THEN uv.value ELSE NULL END) AS Question1',
        'MAX(CASE WHEN uv.user_type_variables_id = 2 THEN uv.value ELSE NULL END) AS Question2',
        'MAX(CASE WHEN uv.user_type_variables_id = 3 THEN uv.value ELSE NULL END) AS Question3',
        'MAX(CASE WHEN uv.user_type_variables_id = 4 THEN uv.value ELSE NULL END) AS Question4',
        'MAX(CASE WHEN uv.user_type_variables_id = 5 THEN uv.value ELSE NULL END) AS Question5',
        'MAX(CASE WHEN uv.user_type_variables_id = 6 THEN uv.value ELSE NULL END) AS Question6',
        // add what you need
    ];
    

    【讨论】:

    • 不幸的是我不能让它工作。不管我告诉它看什么,它仍然在看 eventattendees 表,就像 uv。看起来像用户类型变量问题。我已经添加了我需要的所有关系,但它仍然说找不到该列。我已经在我的 OP 中添加了一种工作的 cdatarrayprovider,但我仍然无法访问模型数据。
    • 活动记录“EventAttendees”正在尝试选择无效列“MAX(CASE WHEN userTypeVariables.user_type_variables_id = 1 THEN userTypeVariables.value ELSE NULL END) Question1”。请注意,该列必须存在于表中或者是具有别名的表达式。但它正在识别这种关系,所以我不明白为什么它找不到该列
    • hmm 好的,启用 CWebLogRoute 以查看执行的查询,以便您可以解决此问题,检查 $criteria->together = true;如果未设置此属性,则设置正确 Yii 将使用延迟加载来访问关系。
    • 是的,关系很好,都在一起。看起来功能将不得不被放弃。不知道为什么框架一开始就很难只使用两个数据提供者!
    • 是的,SQL 在 THEN uv.value ELSE NULL END) Question6 FROM tbl_event_attendees 中完成,似乎完全忽略了它应该来自哪里。 uv 问题来自 user_variable 表。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-07
    • 2014-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多