Двойная агрегация

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
rzhukovskii
Сообщения: 6
Зарегистрирован: 2017.03.04, 14:56

Двойная агрегация

Сообщение rzhukovskii »

Есть таблица car:
number - номер машины
city - город обслуживания
service_date - дата обслуживания

Как решить следующие задачи:
1. вывести сколько машин обслужилось 10 раз, 9 раз, 8 раз и т.д. Составить чистый вложенный sql запрос - легко. Как грамотно сделать это средствами Yii - не придумал.
2. Желательно чтобы эта задача решалась и для варианта: вывести сколько машин обслужилось в таком-то городе. Т.е. в зависимости от какого-то параметра мы решаем либо 1ю, либо 2ю задачу.

Как решить в лоб разными запросами - все понятно. Возможно кто-то сможет предложить какой-то более красивый вариант.
Onotole
Сообщения: 1808
Зарегистрирован: 2012.12.24, 12:49

Re: Двойная агрегация

Сообщение Onotole »

Напишите SQL запрос, а мы поможем составить для yii
caHek2x
Сообщения: 1242
Зарегистрирован: 2016.04.12, 20:41

Re: Двойная агрегация

Сообщение caHek2x »

зачем вложенный запрос ...
select *, count(*) FROM table
2: WHERE city = '....'
GROUP BY number
1: HAVING count(*) = 10

что именно у вас на yii не получилось ? find()->where(['city'=>'...'])->having(['count(*)' => 10])->groupBy....->count();
или все считайте и потом отсортируйте как душе угодно ... ->select(...)->asArray()->all()
rzhukovskii
Сообщения: 6
Зарегистрирован: 2017.03.04, 14:56

Re: Двойная агрегация

Сообщение rzhukovskii »

caHek2x писал(а): 2017.03.04, 16:42 зачем вложенный запрос ...
select *, count(*) FROM table
2: WHERE city = '....'
GROUP BY number
1: HAVING count(*) = 10

что именно у вас на yii не получилось ? find()->where(['city'=>'...'])->having(['count(*)' => 10])->groupBy....->count();
или все считайте и потом отсортируйте как душе угодно ... ->select(...)->asArray()->all()
Нет, мне нужно за один запрос получить сколько машин сколько раз обслуживалось. HAVING здесь не подойдет.
rzhukovskii
Сообщения: 6
Зарегистрирован: 2017.03.04, 14:56

Re: Двойная агрегация

Сообщение rzhukovskii »

Onotole писал(а): 2017.03.04, 16:28 Напишите SQL запрос, а мы поможем составить для yii
SQL такой получается:

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

SELECT 
    servicesCount, COUNT(number) as carsCount
FROM
    (SELECT 
        number, COUNT(number) AS servicesCount
    FROM
        car
    GROUP BY number) counts
GROUP BY servicesCount;
На выходе получаю табличку вроде:
5 машин обслужилось 5 раз
4 машины обслужилось 3 раза
и т.д.
Последний раз редактировалось rzhukovskii 2017.03.04, 17:00, всего редактировалось 2 раза.
rzhukovskii
Сообщения: 6
Зарегистрирован: 2017.03.04, 14:56

Re: Двойная агрегация

Сообщение rzhukovskii »

При чем на выходе желательно получить activeQuery, а не просто query, но не принципиально
caHek2x
Сообщения: 1242
Зарегистрирован: 2016.04.12, 20:41

Re: Двойная агрегация

Сообщение caHek2x »

делаете query ... а потом делаете второй query у которого в from вкладываете первый ...
rzhukovskii
Сообщения: 6
Зарегистрирован: 2017.03.04, 14:56

Re: Двойная агрегация

Сообщение rzhukovskii »

caHek2x писал(а): 2017.03.04, 17:04 делаете query ... а потом делаете второй query у которого в from вкладываете первый ...
Ну как я и писал - решение в лоб мне известно. А вот как сделать это с помощью ActiveRecord и сделать запрос более-менее подходящим под обе задачи в топике - я не знаю.
Видимо никак.
caHek2x
Сообщения: 1242
Зарегистрирован: 2016.04.12, 20:41

Re: Двойная агрегация

Сообщение caHek2x »

всмысле ? причем тут AQ к запросу который вернет данные не относящиеся к модели ...
ну сделайте вложенный через AQ...
у вас всеравно ответ это будет массив ..
(new Query())->from(Car::find()->groupBy(...)->where(....))->where(...)->select()->groupBy(....)
универсальность под обе задачи сделайте условиями ...
if (!empy($city))$query->where(['city'=>...])
или чего вы желаете добиться ... ?
caHek2x
Сообщения: 1242
Зарегистрирован: 2016.04.12, 20:41

Re: Двойная агрегация

Сообщение caHek2x »

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

public static function getStatistics($city=null){
    $subQuery = Car::find()
        ->groupBy(['number'])
        ->select(['number', new Expression("COUNT(number) AS servicesCount")]);
    if (!empty($city)) $subQuery->andWhere(['city'=>$city]);

    $query = (new Query())->from(['counts'=>$subQuery])
        ->select(['servicesCount', new Expression("COUNT(number) as carsCount")])
        ->groupBy(['servicesCount']);

    return $query->all();
}
rzhukovskii
Сообщения: 6
Зарегистрирован: 2017.03.04, 14:56

Re: Двойная агрегация

Сообщение rzhukovskii »

caHek2x писал(а): 2017.03.04, 17:32

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

public static function getStatistics($city=null){
    $subQuery = Car::find()
        ->groupBy(['number'])
        ->select(['number', new Expression("COUNT(number) AS servicesCount")]);
    if (!empty($city)) $subQuery->andWhere(['city'=>$city]);

    $query = (new Query())->from(['counts'=>$subQuery])
        ->select(['servicesCount', new Expression("COUNT(number) as carsCount")])
        ->groupBy(['servicesCount']);

    return $query->all();
}
Наверное это ближе всего к тому, что я хочу. Спасибо!
caHek2x
Сообщения: 1242
Зарегистрирован: 2016.04.12, 20:41

Re: Двойная агрегация

Сообщение caHek2x »

вы просто описывайте что у вас не получается и что вы хотите в итоге ...
ато я вам выше написал, вы меня похоже не поняли и сказали "Ну как я и писал - решение в лоб мне известно"
я описал тоже самое только кодом вы сказали что это то что надо :-D
Ответить