2015-06-24 2 views
1

С Yii framework 2.0 У меня есть две таблицы базы данных, как показано ниже.Yii2: Как создать ActiveDataProvider с помощью запроса объединения и сортировки?

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. Как я могу это сделать?

+0

Есть ли таблица B в столбце 'id' или' a_id'? – robsch

ответ

6

Я не тестировал его. Но она должна работать, как это, я думаю:

$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` 

Он вдохновлен this example в руководстве Yii.

+0

Я пробовал ваш выше код, но он заказывает только записи каждой таблицы, таблицы в таблице, означает, что он сначала заказывает все записи таблицы 'user', а затем только таблицу' customer'. Пример результата упорядочения 'a_id' на основе вашего кода и моей базы данных примеров выше: 1,2,3,1,1,2,2,2,3. Когда я использовал функцию 'sort' из GridView, она по-прежнему остается прежней. То, что я хотел бы подойти, - 1,1,1,2,2,2,2,3,3. Пожалуйста помоги! –

+0

@OConnor Я обновил свой ответ. Как вы видите, я переместил предложение where. Это работает? – robsch

+0

@OConnor Изменен еще раз. Теперь используется подзапрос. Я думаю, что это необходимо. Альтернативой было бы использовать [createCommand()] (http://www.yiiframework.com/doc-2.0/yii-db-connection.html#createCommand%28%29-detail), чтобы построить исходный SQL-оператор, где вы могли бы поместите SQL-код напрямую. – robsch

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 запросов.