Выборка записей с фильтром по количеству связанных записей

Допустим у нас есть 2 простые таблицы, категории блога, и записи в блоге. Запись в блоге находится в одной из категорий. Как бы вы получили список категорий, в которых количество записей больше определенного? Решение прилагаю на Yii фреймворке первой версии, но если вы работаете с другой платформой, то вам не составит труда его адаптировать

Допустим у нас есть 2 простые таблицы, категории блога, и записи в блоге. Запись в блоге находится в одной из категорий. Как бы вы получили список категорий, в которых количество записей больше определенного?

Начинающие программисты, скорее всего будут решать задачу перебором. Выберут все категории, посчитают для них количество записей для каждой категории отдельно. Фильрация по количеству будет уже в скрипте.

Теоретики, без реального опыта работы в сложных проектах, будут пытаться писать один запрос, который решит эту задачу. Однако, если такой запрос попадет в реальный проект с выскокой нагрузкой, их может ждать сюрприз, когда SQL сервер откажется его выполнять с приемлемой скоростью.

Третий вариант как это можно сделать - через вложенные запросы.

На мой взгляд, лучше всего решать эту задачу через временные таблицы. Думаю, вполе можно считать это производным от вложенных запросов, и не выделять как четвертый вариант.

Решение прилагаю на Yii фреймворке первой версии, но если вы работаете с другой платформой, то вам не составит труда его адаптировать. В данном случая на первом месте стоит идея, а не реализация.

Делаю модель: [code] class BlogCategoryCount extends CActiveRecord {

public static $created = FALSE;

public function tableName()
{
    if (static::$created == FALSE)
    {
        Yii::app()->db->createCommand('DROP TABLE IF EXISTS {{blog_category_count}}')->execute();

        $sql = Yii::app()->db
            ->createCommand()
            ->select('t.category_id as category_id, count(t.id) as count')
            ->from('{{blog_post}} t')
            ->group('t.category_id')
            ->text;

        $sql = 'CREATE TEMPORARY TABLE {{blog_category_count}} '.$sql;

        $query = Yii::app()->db->createCommand($sql);

        $query->execute();
    }

    return '{{blog_category_count}}';
}

public function primaryKey()
{
    return 'category_id';
}

} [/code]

В модели категории описываю связь с временной таблицей:

[code] public function relations() { return [ 'categoryCount' => [ self::HAS_ONE, 'BlogCategoryCount', 'category_id' ] ]; }

[/code]

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

[code] public function getCount() { if ($this->categoryCount != FALSE) { return $this->categoryCount->count; }

return 0;

} [/code]

При выборке данных в контроллере присоединяю модель к выборке:

[code] $categories = BlogCategory::model()->findAll([ 'with' => 'categoryCount', 'condition' => 'categoryCount.count>=:count', 'params' => array( ':count' => 1 ) ]); [/code]

09.11.2016