Страница 1 из 1

Как делать сложные или вложенные запросы с помощью QB?

Добавлено: 2019.10.03, 02:25
myks1992@mail.ru
Всем привет!
Делаю радел статистики. Статистика динамическая, из таблиц базы данных MYSQL.

На Active Record, с использованием связей, такие запросы я знаю как сделать. Так как эти связи нужны только для этой статистики, то не хотелось бы захламлять доменную сущность не нужными ей связями. Отсюда возник вопрос как отказаться вообще от AR и построить такой запрос на Query Builder?

Вот пример запроса с использованием AR:

Код: Выделить всё

$query = Certification::find()
            ->alias('c')
            ->select([
                'c.id',
                'c.user_id',
                'c.category_id',
                'TRIM(CONCAT_WS(\' \', p.last_name, p.name)) as user_name',
                'COUNT(DISTINCT appointment.event_id) as appointment_count',
                'category.name as categoryName'
            ])
            ->joinWith([
                'profile as p' => function (ActiveQuery $query) {
                    $query->select(['p.user_id']);
                },
                'appointments' => function (AppointmentQuery $query) {
                    $query->appointed();
                },
                'category' => function (ActiveQuery $query) {
                    $query->select(['category.id', 'category.name']);
                },
            ])
            ->andWhere(['category.role' => Certification::ROLE_JUDGE])
            ->andWhere('FROM_UNIXTIME(appointment.from_at, \'%Y\') = :year', [':year' => $year])
            ->active(true)
            ->valid(true)
            ->addGroupBy('appointment.user_id')
            ->addOrderBy('categoryName DESC')
            ->limit($limit && 0 < $limit && $limit < 1000  ? $limit : 1000)
            ->asArray();
Понимаю, что начало запроса нужно заменить как-то так:

Код: Выделить всё

(new Query())->from('certification') .... 
А вот как мне быть с joinWith()? Как мне сформировать данные в виде массива, при том у связей есть всегда условия...

Благодарю за помощь!

Re: Как делать сложные или вложенные запросы с помощью QB?

Добавлено: 2019.10.03, 06:25
BrusSENS
myks1992@mail.ru писал(а): 2019.10.03, 02:25 А вот как мне быть с joinWith()? Как мне сформировать данные в виде массива, при том у связей есть всегда условия...
Вы можете жадно подтянуть связанные данные, так же, как это делается в AR, условия же у вас идут в обычном join. Думаю, что с Join не возникнет проблем.
В AR связи подтягиваются после выборки основного запроса дополнительными запросами.
Например:
У нас запрос из certificate вернул определённый набор данных.
Мы имеем внешние ключи на profile, appointments, category. Таким образом можно сделать примерно так:

Код: Выделить всё

$categoryIds = array_keys(ArrayHelper::index($result, 'category_id'));
$categories = (new Query())
    ->from('categories')
    ->where(['in', 'id', $categoryIds])
    ->all();
Таким образом мы получили все категории, которые есть в результате $result. Тем же самым способом вытаскиваем значения для profile и appointments.

Re: Как делать сложные или вложенные запросы с помощью QB?

Добавлено: 2019.10.04, 02:05
myks1992@mail.ru
BrusSENS писал(а): 2019.10.03, 06:25
myks1992@mail.ru писал(а): 2019.10.03, 02:25 А вот как мне быть с joinWith()? Как мне сформировать данные в виде массива, при том у связей есть всегда условия...
Вы можете жадно подтянуть связанные данные, так же, как это делается в AR, условия же у вас идут в обычном join. Думаю, что с Join не возникнет проблем.
В AR связи подтягиваются после выборки основного запроса дополнительными запросами.
Например:
У нас запрос из certificate вернул определённый набор данных.
Мы имеем внешние ключи на profile, appointments, category. Таким образом можно сделать примерно так:

Код: Выделить всё

$categoryIds = array_keys(ArrayHelper::index($result, 'category_id'));
$categories = (new Query())
    ->from('categories')
    ->where(['in', 'id', $categoryIds])
    ->all();
Таким образом мы получили все категории, которые есть в результате $result. Тем же самым способом вытаскиваем значения для profile и appointments.
Примерно понял как получать) А массив самому формировать из полученных запросов? Я имею ввиду вложенность...

Re: Как делать сложные или вложенные запросы с помощью QB?

Добавлено: 2019.10.04, 10:04
yiiliveext
BrusSENS писал(а): 2019.10.03, 06:25
У нас запрос из certificate вернул определённый набор данных.
Мы имеем внешние ключи на profile, appointments, category. Таким образом можно сделать примерно так:

Код: Выделить всё

$categoryIds = array_keys(ArrayHelper::index($result, 'category_id'));
$categories = (new Query())
    ->from('categories')
    ->where(['in', 'id', $categoryIds])
    ->all();
Таким образом мы получили все категории, которые есть в результате $result. Тем же самым способом вытаскиваем значения для profile и appointments.
Во-первых, category и profile - это оношения вида hasOne и из них нам надо только поля name и last_name, name соответственно. Все это получается обычным join(). Во-вторых, ваш запрос categories вообще не имеет никакого практического смысла в данном случае.

Re: Как делать сложные или вложенные запросы с помощью QB?

Добавлено: 2019.10.04, 10:11
yiiliveext
myks1992@mail.ru писал(а): 2019.10.04, 02:05 А массив самому формировать из полученных запросов? Я имею ввиду вложенность...
Можете формировать запросом в переменную непосредственно при использовании, а можете пройтись в цикле и сформировать массивы на каждую связь индексированные по айди основной сущности.

Re: Как делать сложные или вложенные запросы с помощью QB?

Добавлено: 2019.10.04, 12:18
myks1992@mail.ru
yiiliveext писал(а): 2019.10.04, 10:11
myks1992@mail.ru писал(а): 2019.10.04, 02:05 А массив самому формировать из полученных запросов? Я имею ввиду вложенность...
Можете формировать запросом в переменную непосредственно при использовании, а можете пройтись в цикле и сформировать массивы на каждую связь индексированные по айди основной сущности.
Понял. Благодарю!) Никогда просто не использовал QB. Но по сути те же SQL запросы.