Yii2:如何使用联合查询和排序创建ActiveDataProvider?

时间:2015-06-24 04:25:18

标签: php sql gridview yii2 union

使用Yii framework 2.0,我有两个数据库表如下。

A table:
   a_id = 1, name = yes, number = 123
   a_id = 2, name = no, number = 456 
   a_id = 3, name = ok,  number = 683

B table:
  id = 1, a_id = 1, firstname = s
  id = 2, a_id = 1, firstname = y
  id = 3, a_id = 2, firstname = e
  id = 4, a_id = 2, firstname = x
  id = 5, a_id = 2, firstname = t
  id = 6, a_id = 3, firstname = r

我想使用ActiveDataProvider为GridView查询这些记录,结果如下。

a_id = 1, name = yes, number = 123
a_id = 1, name = s, number = null
a_id = 1, name = y, number = null
a_id = 2, name = no, number = 456
a_id = 2, name = e, number = null
a_id = 2, name = x, number = null
a_id = 2, name = t, number = null
a_id = 3, name = ok,  number = 683
a_id = 3, name = r, number = null

以下是我正在使用的纯SQL查询。

SELECT `a_id`, `name`, `number` FROM `user` WHERE number != ''
UNION ALL
SELECT `a_id`, `firstname` as name , null as `number` FROM `customer` 
WHERE `firstname` != ''
ORDER BY `a_id` ASC, name ASC 

我想用ActiveDataProvider实现上面的查询。我怎么能这样做?

4 个答案:

答案 0 :(得分:11)

我还没有测试过。但它应该像这样工作,我想:

$query1 = (new \yii\db\Query())
    ->select("a_id, name, number")
    ->from('user')
    ->where(['!=', 'number', '']);

$query2 = (new \yii\db\Query())
    ->select("a_id, firstname as name , null as number")
    ->from('customer')
    ->where(['!=', 'firstname', '']);

$unionQuery = (new \yii\db\Query())
    ->from(['dummy_name' => $query1->union($query2)])
    ->orderBy(['a_id' => SORT_ASC, 'name' => SORT_ASC]);

$provider = new ActiveDataProvider([
    'query' => $unionQuery,
    'pagination' => [
        'pageSize' => 20,
    ],
]);

$rows = $provider->getModels();

它应该创建一个如下所示的查询:

SELECT * FROM 
(
    (SELECT `a_id`, `name`, `number` FROM `user` WHERE `number` != ''   )
    UNION 
    (SELECT `a_id`, `firstname` AS `name`, `null` AS `number` FROM `customer` WHERE `firstname` != '')
) `dummy_name`
ORDER BY `a_id`, `name`

它的灵感来自Yii指南中的this example

答案 1 :(得分:1)

$query1 = (new \yii\db\Query())
    ->select("a_id, name, number")
    ->from('user')
    ->where(['!=', 'number', '']);

$query2 = (new \yii\db\Query())
    ->select("a_id, firstname as name , null as number")
    ->from('customer')
    ->where(['!=', 'firstname', '']);

$query1->union($query2, false);//false is UNION, true is UNION ALL
$sql = $query1->createCommand()->getRawSql();
$sql .= ' ORDER BY id DESC';
$query = User::findBySql($sql);

$dataProvider = new ActiveDataProvider([
    'query' => $query,              
]);

这应该有效,似乎有一个bug不允许正确排序UNION查询。

答案 2 :(得分:1)

以下代码已在我的模型“ CoinsHistorySearch.php”中进行了测试,希望对某些人有所帮助。

AFN Afghan Afghani  73.0556951371   0.0136881868
ALL Albanian Lek    108.3423252926  0.0092300031
DZD Algerian Dinar  117.9799583224  0.0084760159
AOA Angolan Kwanza  249.2606313396  0.0040118650
ARS Argentine Peso  28.2508833695   0.0353971232
AMD Armenian Dram   482.0941933740  0.0020742834

答案 3 :(得分:0)

这可能对某人有帮助

// Query Table A
$tableA = (new \yii\db\Query())
         ->select("a_id, name, number")
         ->from('user')
         ->where(['!=', 'number', '']);

// Query table B
$tableB = (new \yii\db\Query())
         ->select("a_id, firstname as name , null as number")
         ->from('customer')
         ->where(['!=', 'firstname', '']);

// Union table A and B
$tableA->union($tableB);

/*
 * Table A is your Model
 * find() method in activeRecord will load the instance of ActiveQuery
 * Now you can use base Query methods like select and from on find() method
 */
$query = TableA::find()->select('*')->from(['random_name' => $tableA]);

// Dataprovider
$dataProvider = new ActiveDataProvider([
   'query' => $query,
   'pagination' => [
      'pageSize' => 20,
    ],
   'sort'=> ['defaultOrder' => ['a_id' => SORT_ASC]],
]);

//Search filters and grid filters can go here

return $dataProvider;

所有搜索过滤器以及网格中的关系都应使用此方法。