Below is my pure SQL query.
SELECT a.*, b.*
FROM a
INNER JOIN b
ON a.id = b.a_id
INNER JOIN (
SELECT a_id, MAX(add_time) AS max_add_time
FROM b
GROUP BY a_id
) m
ON b.a_id = m.a_id AND b.add_time = m.max_add_time
ORDER BY b.add_time DESC
I have the subquery in the second INNER JOIN
. Below my active query.
$subQuery = B::find()->select(['a_id', 'MAX(add_time) AS max_add_time'])->groupBy('a_id');
$query = A::find()->innerJoin('b', 'a.id = b.a_id')
->innerJoin('(' .
$subQuery->prepare(Yii::$app->db->queryBuilder)
->createCommand()
->rawSql
. ') m', 'b.a_id = m.a_id AND a.add_time = m.max_add_time ')
->orderBy('b.add_time DESC');
It works fine, but I do not like the way I use the subquery in the second INNER JOIN
. What I want to approach with this query is to select the left table inner join with right table, group by a_id
and order by the add_time (DESC) of the right table. How should I better use the subquery in the second INNER JOIN?
A subquery can be used with JOIN operation. In the example below, the subquery actually returns a temporary table which is handled by database server in memory. The temporary table from the subquery is given an alias so that we can refer to it in the outer select statement.
use createcommand() method: use yii\db\Query(); $connection = \Yii::$app->db; $query = new Query; $insql = $connection->createCommand("SELECT* FROM inventory ); $result=$insql->queryAll(); the above method list all data from the inventory table.
An ActiveQuery can be a normal query or be used in a relational context. ActiveQuery instances are usually created by yii\db\ActiveRecord::find() and yii\db\ActiveRecord::findBySql(). Relational queries are created by yii\db\ActiveRecord::hasOne() and yii\db\ActiveRecord::hasMany().
The snippet below is untested but it should be something like that. If you read the docs (at http://www.yiiframework.com/doc-2.0/yii-db-query.html#innerJoin()-detail) you can see an array with a subquery is also valid input, with the key being the alias.
$subQuery = B::find()
->select(['a_id', 'MAX(add_time) AS max_add_time'])
->groupBy('a_id');
$query = A::find()
->innerJoin('b', 'a.id = b.a_id')
->innerJoin(['m' => $subQuery], 'b.a_id = m.a_id AND a.add_time = m.max_add_time')
->orderBy('b.add_time DESC');
Having created the join, if you need to use any of the columns returned by the subQuery, you need to add properties to the Yii2 model class, e.g.
$subQuery = FinancialTransaction::find()
->select( new \yii\db\Expression( 'SUM(amount) as owing') )
->addSelect('booking_id')
->groupBy('booking_id');
$query = $query
->addSelect(['b.*', 'owing'])
->leftJoin(['ft' => $subQuery], 'b.booking_display_id = ft.booking_id');
To access "owing" the model has to have the property (PHPdoc optional):
/**
* @var float
*/
public $owing=0;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With