Как в Yii2 можно сделать сортировку по вычисляемому рейтингу и по кол-ву связанных данных?

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
EVOSandru6
Сообщения: 605
Зарегистрирован: 2014.07.04, 13:33

Как в Yii2 можно сделать сортировку по вычисляемому рейтингу и по кол-ву связанных данных?

Сообщение EVOSandru6 »

Добрый вечер,

Есть такие таблицы:

users
----------------
id
name
----------------

departments
----------------
id
name
----------------

news
----------------
id
department_id
name
----------------

events
----------------
id
department_id
name
----------------

rating_departments
----------------
department_id
user_id
rate
----------------

Мне нужно сделать:

1) Вывод модели Departments по рейтингу по убыванию

2) Вывод модели Departments по убыванию кол-ва привязанных к нему новостей и событий. С учетом суммарного кол-ва и тех и тех.

Желательно скормить желаемую сортировку для DepartmentsSearch класса или хотя бы для модели

Исходные модели:

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

class Departments extends ActiveRecord
{
...
    public function getEvents()
    {
        return $this->hasMany(Events::className(), ['department_id' => 'id']);
    }

    public function getNews()
    {
        return $this->hasMany(News::className(), ['department_id' => 'id']);
    }

     public function getRatingSum()
    {
        $val = RatingDepartments::find()->andWhere([
            'department_id' => $this->department_id,
        ])->sum('rate');
        return $val ?? 0;
    }

    public function getRatingQty()
    {
        $val = RatingDepartments::find()->andWhere([
            'department_id' => $this->department_id,
        ])->count();
        return $val;
    }

    public function getRate()
    {
        $sum = $this->getRatingSum();
        $qty = $this->getRatingQty();
        if(!$qty)
            return 0;
        $rate = ceil($sum / $qty);
        return $rate;
    }
...
}

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

class RatingDepartments extends ActiveRecord
{
  ...
    public function getUser()
    {
        return $this->hasOne(Users::className(), ['id' => 'user_id']);
    }

    public function getDepartment()
    {
        return $this->hasOne(Departments::className(), ['id' => 'department_id']);
    }
    ...
}

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

class News extends ActiveRecord
{
...
public function getDepartment()
    {
        return $this->hasOne(Departments::className(), ['id' => 'department_id']);
    }
...
}

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

class News extends ActiveRecord
{
...
public function getDepartment()
    {
        return $this->hasOne(Departments::className(), ['id' => 'department_id']);
    }
...
}

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

class Events extends ActiveRecord
{
...
public function getDepartment()
    {
        return $this->hasOne(Departments::className(), ['id' => 'department_id']);
    }
...
}
https://nix-tips.ru/yii2-sortirovka-i-f ... olyam.html смотрел. Но этот вариант не совсем подходит, чую тут нужен какой то хитровыдуманный SQL запрос.

Также понимаю криворукость метода getRate, надо как то одним запросом результат доставать, но лучшего решения я пока не знаю.

Заранее благодарю за любую помощь
Nex-Otaku
Сообщения: 831
Зарегистрирован: 2016.07.09, 21:07

Re: Как в Yii2 можно сделать сортировку по вычисляемому рейтингу и по кол-ву связанных данных?

Сообщение Nex-Otaku »

Просто загружаешь в массив и сортируешь по любому полю. Если ArrayHelper использовать, то код чуть компактнее будет.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Как в Yii2 можно сделать сортировку по вычисляемому рейтингу и по кол-ву связанных данных?

Сообщение zelenin »

Nex-Otaku писал(а): 2017.11.13, 01:01 Просто загружаешь в массив и сортируешь по любому полю. Если ArrayHelper использовать, то код чуть компактнее будет.
и часто вы выгружаете в миллион записей для сортировки по ним?
Pa3Py6aka
Сообщения: 10
Зарегистрирован: 2016.07.12, 00:58

Re: Как в Yii2 можно сделать сортировку по вычисляемому рейтингу и по кол-ву связанных данных?

Сообщение Pa3Py6aka »

Для выборки просто по рейтингу можно в DepartsmentSearch в провайдер скормить что-то типа такого запроса:

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

Departments::find()
    ->alias('d')
    ->innerJoin(RatingDepartments::tableName() . ' rd', 'd.id=rd.department_id')
    ->addSelect('d.*,SUM(rd.rate) rateSum')
    ->groupBy('d.id')
    ->orderBy(['rateSum' => SORT_DESC])
Если нужно выводить значение рейтинга, то, насколько я помню, в Departments нужно прописать public $rateSum.

А для второй задачи я бы наверное добавил в таблицу departments дополнительное поле и при добавлении/удалении новостей и событий обновлял бы это поле.
EVOSandru6
Сообщения: 605
Зарегистрирован: 2014.07.04, 13:33

Re: Как в Yii2 можно сделать сортировку по вычисляемому рейтингу и по кол-ву связанных данных?

Сообщение EVOSandru6 »

Pa3Py6aka писал(а): 2017.11.13, 03:52 Для выборки просто по рейтингу можно в DepartsmentSearch в провайдер скормить что-то типа такого запроса:

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

Departments::find()
    ->alias('d')
    ->innerJoin(RatingDepartments::tableName() . ' rd', 'd.id=rd.department_id')
    ->addSelect('d.*,SUM(rd.rate) rateSum')
    ->groupBy('d.id')
    ->orderBy(['rateSum' => SORT_DESC])
Если нужно выводить значение рейтинга, то, насколько я помню, в Departments нужно прописать public $rateSum.

А для второй задачи я бы наверное добавил в таблицу departments дополнительное поле и при добавлении/удалении новостей и событий обновлял бы это поле.

Благодарю. Опрбую данное чудо.

По поводу второго вопроса:

В модели Departments добавил метод - примерно то, что мне надо:

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

public static function  getProviderByTotalParams()
    {
        $mainTable = self::tableName();

        $sql = '
             SELECT m_departments.id, m_departments.name, 
             COUNT(m_news.id) + COUNT(m_posts.id) + COUNT(m_forums.id) + COUNT(m_questions.id) AS total_count
            FROM m_departments 
            LEFT JOIN m_news ON m_departments.id = m_news.department_id
            LEFT JOIN m_posts ON m_departments.id = m_posts.department_id
            
            GROUP BY m_departments.id
            ORDER BY total_count DESC
            LIMIT 5
        ';

        $dataProvider = new SqlDataProvider([
            'sql' => $sql, 
            'totalCount' => 5, 
            'pagination' => [
                'pageSize' => 5, 
            ],
        ]);;

        return $dataProvider;
    }
Pa3Py6aka
Сообщения: 10
Зарегистрирован: 2016.07.12, 00:58

Re: Как в Yii2 можно сделать сортировку по вычисляемому рейтингу и по кол-ву связанных данных?

Сообщение Pa3Py6aka »

EVOSandru6 писал(а): 2017.11.13, 07:10 По поводу второго вопроса:
В модели Departments добавил метод - примерно то, что мне надо
Не уверен что он будет работать, попробуйте выполнить этот запрос в таком виде:

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

SELECT m_departments.id, m_departments.name, 
COUNT(m_news.id), COUNT(m_posts.id)
FROM m_departments 
LEFT JOIN m_news ON m_departments.id = m_news.department_id
LEFT JOIN m_posts ON m_departments.id = m_posts.department_id
GROUP BY m_departments.id
LIMIT 100
И посмотрите что вернётся в колонках COUNT(m_news.id) и COUNT(m_posts.id). Там могут быть одинаковые значения в обоих колонках, по максимальному числу строк для каждой записи. Ну это я не уверен, потестируйте.
EVOSandru6
Сообщения: 605
Зарегистрирован: 2014.07.04, 13:33

Re: Как в Yii2 можно сделать сортировку по вычисляемому рейтингу и по кол-ву связанных данных?

Сообщение EVOSandru6 »

Благодарю! Только в вашем случае с сортирокой неясно - как быть. У меня это total_count, а у Вас 2 разных каунта.
Pa3Py6aka
Сообщения: 10
Зарегистрирован: 2016.07.12, 00:58

Re: Как в Yii2 можно сделать сортировку по вычисляемому рейтингу и по кол-ву связанных данных?

Сообщение Pa3Py6aka »

Вы не поняли, этот запрос я предлагаю выполнить чтобы просто проверить что в результате получается. Если в колонках COUNT(m_news.id) и COUNT(m_posts.id) будут нужные значения(например 5 и 10 - по кол-ву новостей и постов всё соответсвует), тогда используйте Ваш запрос где Вы суммируете эти полученные значения и сортируете по ним. Ну или не изменяя Ваш запрос посмотрите что он возвращает и сравните с реальными данными.
Nex-Otaku
Сообщения: 831
Зарегистрирован: 2016.07.09, 21:07

Re: Как в Yii2 можно сделать сортировку по вычисляемому рейтингу и по кол-ву связанных данных?

Сообщение Nex-Otaku »

zelenin писал(а): 2017.11.13, 02:37
Nex-Otaku писал(а): 2017.11.13, 01:01 Просто загружаешь в массив и сортируешь по любому полю. Если ArrayHelper использовать, то код чуть компактнее будет.
и часто вы выгружаете в миллион записей для сортировки по ним?
Вопрос был в том, "как можно сделать", а не "как правильно сделать". Самый простой способ я предложил, далее всё в руках автора поста )

Ну а вообще это вброс был для вашей реакции. Вот мне лично было лень писать SQL-запрос. Смотрю, что автору поста никто не ответил, и я решил, что если "неправильный" способ предложить, уж тогда-то обязательно кто-то возьмётся меня "разоблачить" и составить нужный запрос ) Так и вышло ;) Негативная мотивация лучше работает )

Кстати, для экспериментов с запросами рекомендую песочницу sqlfiddle. Удобная штука.
Pa3Py6aka
Сообщения: 10
Зарегистрирован: 2016.07.12, 00:58

Re: Как в Yii2 можно сделать сортировку по вычисляемому рейтингу и по кол-ву связанных данных?

Сообщение Pa3Py6aka »

Nex-Otaku писал(а): 2017.11.14, 22:14 Так и вышло ;)
Вообще-то ничего не вышло, я - не зеленин :lol:
Nex-Otaku
Сообщения: 831
Зарегистрирован: 2016.07.09, 21:07

Re: Как в Yii2 можно сделать сортировку по вычисляемому рейтингу и по кол-ву связанных данных?

Сообщение Nex-Otaku »

Ну в общем просто привлечь внимание хотел. Задачка-то интересная.
fedornabilkin
Сообщения: 17
Зарегистрирован: 2017.09.23, 15:17

Re: Как в Yii2 можно сделать сортировку по вычисляемому рейтингу и по кол-ву связанных данных?

Сообщение fedornabilkin »

Здравствуйте. У меня похожая задача и что-то не получается. Есть таблица с историей:
id
uid_test
uid_person
points

Необходимо получить сумму баллов всех тестов для каждого пользователя.
Делаю запрос:

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

$query = History::find()
            ->select('SUM(points) as point_all, uid_person')
            ->where(['id' => $this->nn_quiz['ids']])
            ->andFilterWhere(['uid_person' => $this->uid_person])
            ->groupBy('uid_person')
        ;
        
        var_dump($query->limit(15)->all());exit;
Получаю только uid_person

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

array (size=1)
          'uid_person' => int 148565
Что я делаю не так? Как получить points_all и сортировать по этому полю по убыванию?
Loveorigami
Сообщения: 977
Зарегистрирован: 2014.08.27, 21:54

Re: Как в Yii2 можно сделать сортировку по вычисляемому рейтингу и по кол-ву связанных данных?

Сообщение Loveorigami »

потому что сумма не просчитывается. Возможно, из-за этого условия
->where(['id' => $this->nn_quiz['ids']]).
Nex-Otaku
Сообщения: 831
Зарегистрирован: 2016.07.09, 21:07

Re: Как в Yii2 можно сделать сортировку по вычисляемому рейтингу и по кол-ву связанных данных?

Сообщение Nex-Otaku »

Вы пытаетесь результаты запроса загрузить в модель, а в модели атрибута "points_all" не существует, поэтому он и "исчезает", игнорируется. Выгружайте результаты напрямую через вызов "asArray".
fedornabilkin
Сообщения: 17
Зарегистрирован: 2017.09.23, 15:17

Re: Как в Yii2 можно сделать сортировку по вычисляемому рейтингу и по кол-ву связанных данных?

Сообщение fedornabilkin »

Совершенно верно, благодарю. Ошибка из-за невнимательности.
Ответить