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

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
myks1992@mail.ru
Сообщения: 147
Зарегистрирован: 2017.11.15, 23:54

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

Сообщение 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()? Как мне сформировать данные в виде массива, при том у связей есть всегда условия...

Благодарю за помощь!
Аватара пользователя
BrusSENS
Сообщения: 565
Зарегистрирован: 2012.07.26, 06:51
Откуда: Новороссийск
Контактная информация:

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

Сообщение 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.
Native Web - небольшой блог о веб разработке (временно на ремонте)
Режим обслуживания сайта для Yii 2.x.x
myks1992@mail.ru
Сообщения: 147
Зарегистрирован: 2017.11.15, 23:54

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

Сообщение 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.
Примерно понял как получать) А массив самому формировать из полученных запросов? Я имею ввиду вложенность...
yiiliveext
Сообщения: 910
Зарегистрирован: 2019.08.13, 01:49

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

Сообщение 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 вообще не имеет никакого практического смысла в данном случае.
yiiliveext
Сообщения: 910
Зарегистрирован: 2019.08.13, 01:49

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

Сообщение yiiliveext »

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

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

Сообщение myks1992@mail.ru »

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