1

I have a table with lots of listings with a date column.

Usually I show all listings within a date rage using active record like this:

return $this->hasMany(Ranking::className(), ['project_hash' => 'hash'])
        ->where(['>', 'date', date('Y-m-d', strtotime("-8 weeks"))]);  

The output is then a table with all the listings sorted by date, which is once a week as the app collects data.

I need to have an alternate view which shows the output by month, for which I have a working sql query, but I can't get it to work in Yii2. I am using the querybuilder as this seems the right route to build a more complex query.

The raw sql is:

SELECT r.*
FROM ranking AS r
JOIN (
    SELECT MAX(t.date) AS date
    FROM ranking AS t
    GROUP BY YEAR(t.date), MONTH(t.date)
    ) AS x USING (date)
where project_hash = 'TFQDaZ4CZpqvJtvF';

So far I have this code with the querybuilder but it outputs all items

$subQuery = (new \yii\db\Query())
->select(['MAX(t.date) AS date'])
->from('ranking AS t')
->groupBy(['YEAR(t.date)', 'MONTH(t.date)']);


$rows = (new \yii\db\Query())
->select(['r.*'])
->from('ranking AS r')
->innerJoin(['x' => $subQuery])
->where(['project_hash' => 'TFQDaZ4CZpqvJtvF'])
->all();
foreach ($rows as $rank) {
  echo 'key'.$rank['keyword'].' date:'.$rank['date'].'<br>';
};

The sql generated is:

SELECT `r`.* 
FROM `ranking` `r` 
INNER JOIN (
    SELECT MAX(t.date) AS date 
    FROM `ranking` `t` 
    GROUP BY YEAR(t.date), MONTH(t.date)) `x` 
WHERE `project_hash`='TFQDaZ4CZpqvJtvF'

Is it possible to create this query with the querybuilder? I have tried different methods that mostly result in errors, and I can't seem to get the 'AS''s in the right place or get the USING clause in there at all.

Any help is appreciated!

1 Answer 1

1

Try this One

$subQuery = (new \yii\db\Query())
        ->select(['MAX(t.date) AS date'])
        ->from('ranking AS t')
        ->groupBy(['YEAR(t.date)', 'MONTH(t.date)']);


    $rows = (new \yii\db\Query())
        ->select(['r.*'])
        ->from('ranking AS r')
        ->innerJoin(['x USING (date)' => $subQuery])
        ->where(['project_hash' => 'TFQDaZ4CZpqvJtvF'])
        ->createCommand()->rawSql;

It will create Query Like

SELECT `r`.* FROM `ranking` `r` 
INNER JOIN (
 SELECT MAX(t.date) AS date 
 FROM `ranking` `t` 
 GROUP BY YEAR(t.date), MONTH(t.date)
) x USING (date) 
WHERE `project_hash`='TFQDaZ4CZpqvJtvF'
Sign up to request clarification or add additional context in comments.

2 Comments

Perfect thank you! I had just resorted to raw sql and then saw this. To anyone else finding this, the above will output the raw query, to get it to run, substitute rawSql for ->queryAll()
Can you allow my edit incase anyone else finds this and wants to use active record?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.