Yii2 - left join on multiple condition

后端 未结 3 2033
醉话见心
醉话见心 2021-01-12 14:25

I have three tables with the following relations,

  ------- 1        0..* ------------
 |Product|-------------|Availability|
  -------               --------         


        
相关标签:
3条回答
  • 2021-01-12 14:28

    Just use like below condition.

    $query = Product::find()
     -> leftJoin('availability', 'availability.productID=product.ID  AND a.start>=DATE_ADD(DATE(now()), INTERVAL 7 DAY)')
     ->leftJoin('meta_data', 'meta_data.ID=product.meta_dataID')
     ->where(['is', 'availability.ID', NULL])
     ->andWhere(['=', 'meta_data.published_state', 1])
     ->all();
    
    0 讨论(0)
  • 2021-01-12 14:43

    Use this:

    $sql = 'SELECT p.ID FROM product p 
    LEFT JOIN availability a ON a.productID=p.ID 
              AND a.start>=DATE_ADD(DATE(now()), INTERVAL 7 DAY)
    LEFT JOIN meta_data m ON m.ID=p.meta_dataID
    WHERE a.ID IS NULL
    AND m.published_state=1';
    
    $products = Product::findBySql($sql);
    

    Yii Active Record has a findBySql($sql) method that allows you to run and get the data from database using a raw SQL query. It helps a lot when you got confused with Yii's query method or when your query get more complicated to be ran with Yii as in your case I suppose.

    So basically, in above block of codes, you just put your raw SQL query to a variable called $sql, and use it as the parameter value of findBySql() method.

    0 讨论(0)
  • 2021-01-12 14:50

    I believe this one is better solution. Instead of using Raw queries like leftJoin you should complement your joinWith relations with andOnCondition (which adds needed where conditions into your join statement).

    $products = Product::find()
        ->joinWith(['metaData' => function (ActiveQuery $query) {
            return $query
                ->andWhere(['=', 'meta_data.published_state', 1]);
        }])
        ->joinWith(['availability' => function (ActiveQuery $query) {
            return $query
                ->andOnCondition(['>=', 'availability.start', strtotime('+7 days')])
                ->andWhere(['IS', 'availability.ID', NULL]);
        }])
        ->all();
    

    In addition it looks cleaner when you write where clauses inside relations. It works the same as writing it outside (if I'm not wrong), but when refactoring your query, you can easily delete the whole relation without forgetting relation conditions outside.

    0 讨论(0)
提交回复
热议问题