Commit 5829020e by Qiang Xue

Fixes #5223: Query builder now supports selecting sub-queries as columns

parent 48ec791e
...@@ -85,6 +85,15 @@ When specifying columns, you may include the table prefixes or column aliases, e ...@@ -85,6 +85,15 @@ When specifying columns, you may include the table prefixes or column aliases, e
If you are using array to specify the columns, you may also use the array keys to specify the column aliases, If you are using array to specify the columns, you may also use the array keys to specify the column aliases,
e.g., `['user_id' => 'user.id', 'user_name' => 'user.name']`. e.g., `['user_id' => 'user.id', 'user_name' => 'user.name']`.
Starting from version 2.0.1, you may also select sub-queries as columns. For example,
```php
$subQuery = (new Query)->select('COUNT(*)')->from('user');
$query = (new Query)->select(['id', 'count' => $subQuery])->from('post');
// $query represents the following SQL:
// SELECT `id`, (SELECT COUNT(*) FROM `user`) AS `count` FROM `post`
```
To select distinct rows, you may call `distinct()`, like the following: To select distinct rows, you may call `distinct()`, like the following:
```php ```php
......
...@@ -5,6 +5,7 @@ Yii Framework 2 sphinx extension Change Log ...@@ -5,6 +5,7 @@ Yii Framework 2 sphinx extension Change Log
----------------------- -----------------------
- Bug #5601: Simple conditions in Query::where() and ActiveQuery::where() did not allow `yii\db\Expression` to be used as the value (cebe, stevekr) - Bug #5601: Simple conditions in Query::where() and ActiveQuery::where() did not allow `yii\db\Expression` to be used as the value (cebe, stevekr)
- Enh #5223: Query builder now supports selecting sub-queries as columns (qiangxue)
2.0.0 October 12, 2014 2.0.0 October 12, 2014
......
...@@ -446,6 +446,9 @@ class QueryBuilder extends Object ...@@ -446,6 +446,9 @@ class QueryBuilder extends Object
if ($column instanceof Expression) { if ($column instanceof Expression) {
$columns[$i] = $column->expression; $columns[$i] = $column->expression;
$params = array_merge($params, $column->params); $params = array_merge($params, $column->params);
} elseif ($column instanceof Query) {
list($sql, $params) = $this->build($column, $params);
$columns[$i] = "($sql) AS " . $this->db->quoteColumnName($i);
} elseif (is_string($i)) { } elseif (is_string($i)) {
if (strpos($column, '(') === false) { if (strpos($column, '(') === false) {
$column = $this->db->quoteColumnName($column); $column = $this->db->quoteColumnName($column);
......
...@@ -8,13 +8,13 @@ Yii Framework 2 Change Log ...@@ -8,13 +8,13 @@ Yii Framework 2 Change Log
- Bug #5584: `yii\rbac\DbRbacManager` should not delete items when deleting a rule on a database not supporting cascade update (mdmunir) - Bug #5584: `yii\rbac\DbRbacManager` should not delete items when deleting a rule on a database not supporting cascade update (mdmunir)
- Bug #5601: Simple conditions in Query::where() and ActiveQuery::where() did not allow `yii\db\Expression` to be used as the value (cebe, stevekr) - Bug #5601: Simple conditions in Query::where() and ActiveQuery::where() did not allow `yii\db\Expression` to be used as the value (cebe, stevekr)
- Bug: Gii console command help information does not contain global options (qiangxue) - Bug: Gii console command help information does not contain global options (qiangxue)
- Enh #5223: Query builder now supports selecting sub-queries as columns (qiangxue)
- Enh #5587: `json_encode` is now used with `JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE` where it makes sense, also - Enh #5587: `json_encode` is now used with `JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE` where it makes sense, also
it is now default for `Json::encode()` (samdark) it is now default for `Json::encode()` (samdark)
- Enh #5600: Allow configuring debug panels in `yii\debug\Module::panels` as panel class name strings (qiangxue) - Enh #5600: Allow configuring debug panels in `yii\debug\Module::panels` as panel class name strings (qiangxue)
- Enh #5613: Added `--overwrite` option to Gii console command to support overwriting all files (motin, qiangxue) - Enh #5613: Added `--overwrite` option to Gii console command to support overwriting all files (motin, qiangxue)
- Enh #5646: Call `yii\base\ErrorHandler::unregister()` instead of `restore_*_handlers` directly (aivus) - Enh #5646: Call `yii\base\ErrorHandler::unregister()` instead of `restore_*_handlers` directly (aivus)
2.0.0 October 12, 2014 2.0.0 October 12, 2014
---------------------- ----------------------
......
...@@ -626,6 +626,9 @@ class QueryBuilder extends \yii\base\Object ...@@ -626,6 +626,9 @@ class QueryBuilder extends \yii\base\Object
if ($column instanceof Expression) { if ($column instanceof Expression) {
$columns[$i] = $column->expression; $columns[$i] = $column->expression;
$params = array_merge($params, $column->params); $params = array_merge($params, $column->params);
} elseif ($column instanceof Query) {
list($sql, $params) = $this->build($column, $params);
$columns[$i] = "($sql) AS " . $this->db->quoteColumnName($i);
} elseif (is_string($i)) { } elseif (is_string($i)) {
if (strpos($column, '(') === false) { if (strpos($column, '(') === false) {
$column = $this->db->quoteColumnName($column); $column = $this->db->quoteColumnName($column);
......
...@@ -422,4 +422,20 @@ class QueryBuilderTest extends DatabaseTestCase ...@@ -422,4 +422,20 @@ class QueryBuilderTest extends DatabaseTestCase
list($actualQuerySql, $queryParams) = $this->getQueryBuilder()->build($query); list($actualQuerySql, $queryParams) = $this->getQueryBuilder()->build($query);
$this->assertEquals($expectedQuerySql, $actualQuerySql); $this->assertEquals($expectedQuerySql, $actualQuerySql);
} }
public function testSelectSubquery()
{
$subquery = (new Query())
->select('COUNT(*)')
->from('operations')
->where('account_id = accounts.id');
$query = (new Query())
->select('*')
->from('accounts')
->addSelect(['operations_count' => $subquery]);
list ($sql, $params) = $this->getQueryBuilder()->build($query);
$expected = 'SELECT *, (SELECT COUNT(*) FROM `operations` WHERE account_id = accounts.id) AS `operations_count` FROM `accounts`';
$this->assertEquals($expected, $sql);
$this->assertEmpty($params);
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment