简体   繁体   中英

Yii2 : Converting a raw query into ActiveRecord

I have a query which goes into this way.

select t.id,
  t.ad_id,
  sum(t.impression) total_impression,
  sum(t.view) total_views,
  sum(t.clicks) total_clicks,
  t.publisher_id,
  i.budget,
  i.name_of_campaign
from
  (select id,
     ad_id,
     max(impression)  impression,
     max(view)  view,
     max(clicks)  clicks,
     visitor_ip,
     publisher_id
  from ad_analytics
  group by ad_id, visitor_ip) t
  inner join inventory i
             on i.id = t.ad_id
group by t.ad_id;

I want to convert the same for yii2. The query which I have written is.

//For model
use frontend\models\Inventory;
use frontend\models\Adanalytics;

And for grid view in the same model.

$ivcsubquery = Adanalytics::find()->
                  select('id,ad_id,date_event,max(cpc) cpclick,max(cpv) cpview,max(impression) impression,max(view) view,max(clicks) clicks,visitor_ip,publisher_id')->
                  from('ad_analytics')->
                  where(['publisher_id' =>  Yii::$app->user->identity->id ])->
                  groupBy('ad_id,date_event,visitor_ip');
        $ivcquery=Adanalytics::find()->
                // $subquery = select('id,ad_id,max(impression) impression,max(view) view,max(clicks) clicks,visitor_ip,publisher_id')->
                //     from('ad_analytics'),
              //where(['publisher_id' =>  Yii::$app->user->identity->id ])->
              select('t.ad_id,t.date_event,sum(t.cpclick) total_click_cost,sum(t.cpview) total_view_cost,sum(t.impression) total_impression,sum(t.view) total_views,sum(t.clicks) total_clicks,t.publisher_id')->
              from(['t'=>$ivcsubquery])->
              groupBy('t.ad_id,t.date_event');



      $query = Inventory::find()->
      where(['publisher_name' =>  Yii::$app->user->identity->id ])->
      andWhere('ending_date>= NOW()')->
      andWhere('paid=1')->
      andWhere('status=1');

      $joinquery = "Really I don't know what to write down here";

And in my grid view which looks like this.

  'columns' => [
            ['class' => 'yii\grid\SerialColumn'],

            //'id',
            'user_id',
            'placed_date',
            'name_of_campaign',
            'budget',
            //'start_date',
            //'platformType',
            'titleOfTheVideo',
            'videoUrl',
            'ending_date',
   ]

Also columns are called in at the above way How can i solve this issue?

Try this Query . This query return records as array.

$connection = \Yii::$app->db;
$model = $connection->createCommand('
                                  select t.id,
                                    t.ad_id,
                                    sum(t.impression) total_impression,
                                    sum(t.view) total_views,
                                    sum(t.clicks) total_clicks,
                                    t.publisher_id,
                                    i.budget,
                                    i.name_of_campaign
                                  from
                                    (select id,
                                       ad_id,
                                       max(impression)  impression,
                                       max(view)  view,
                                       max(clicks)  clicks,
                                       visitor_ip,
                                       publisher_id
                                    from ad_analytics
                                    group by ad_id, visitor_ip) t
                                    inner join inventory i
                                               on i.id = t.ad_id
                                  group by t.ad_id;
                                ');
$users = $model->queryAll();

If the RawSql query you wrote is giving you the desired results if run on the table using phpmyadmin or any other utility you can transform it into the following.

$subQuery = Adanalytics::find()
        ->select([new Expression('[[id]], [[ad_id]], MAX([[impression]]) as impression, max([[view]]) as view, max([[clicks]]) as clicks,[[visitor_ip]],[[publisher_id]]')])
        ->where(['publisher_id' =>  Yii::$app->user->identity->id ])->
        ->groupBy('[[id]], [[visitor_ip]]');

$query = Adanalytics::find()
        ->select([new \yii\db\Expression('t.[[date_event]], t.[[id]], t.[[ad_id]], sum(t.[[impression]]) as total_impression, sum(t.[[view]]) 
         as total_views, sum(t.[[clicks]]) as total_clicks, t.[[publisher_id]], i.[[budget]],i.[[name_of_campaign]]')])
        ->from(['t' => $subQuery])
        ->innerJoin('{{%inventory}} i', 'i.id=t.ad_id')
        ->groupBy('t.ad_id, t.date_event');
$query->all()

Just make sure that the foreign keys that you use to join the other tables should be specified in the select otherwise it may give you an error like column not found / or unknown column.

If you have a working SQL query you may consider using SqlDataProvider instead of rewriting the whole query:

$sql = <<<'SQL'
from
  (select id,
     ad_id,
     max(impression)  impression,
     max(view)  view,
     max(clicks)  clicks,
     visitor_ip,
     publisher_id
  from ad_analytics
  group by ad_id, visitor_ip) t
  inner join inventory i
             on i.id = t.ad_id
group by t.ad_id;
SQL;

$selectSql = <<<SQL
select t.id,
  t.ad_id,
  sum(t.impression) total_impression,
  sum(t.view) total_views,
  sum(t.clicks) total_clicks,
  t.publisher_id,
  i.budget,
  i.name_of_campaign
$sql
SQL;

$countSql = 'select count(*) ' . $sql;

$dataProvider = new SqlDataProvider([
    'sql' => $selectSql,
    'totalCount' => Yii::$app->db->createCommand($countSql)->queryScalar(),
    'pagination' => [
        'pageSize' => 20,
    ],
]);

The task was one-time and sounded like "get only those orders from the old database, information about which is available in the new database."

    $limit = 1000;

    if( $type = 'viaRawSQL' ) {

        $sql = <<<SQL

    SELECT * FROM db1.orders
    LEFT JOIN db2.orders ON db1.orders.order_id = db2.orders.order_id
    WHERE db2.orders.order_id IS NOT NULL
    LIMIT $limit

    SQL;

        $activeQuery = new ActiveQuery( OrderOld::class );

        $activeQuery->sql = $sql;

    }
    else if( $type == 'viaModel' ) {

        $activeQuery = OrderNew::find()
                               ->where( [
                                   'vat' => null,
                               ] )
                               ->andWhere( [
                                   'not', [ 'invoice_number' => null, ],
                               ] )
                               ->limit( $limit )
        ;
    }

    $dataProvider = new ActiveDataProvider( [
        'query' => $activeQuery,
        'sort'  => [ 'defaultOrder' => [ 'order_id' => SORT_DESC ] ],
    ] );

    // OR get all models
    $index = $activeQuery->all();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM