Допустим у нас есть 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