
Используются 2 таблицы: shop_categories и shop_products (которая имеет поле для связи "category_id").
Подсчет кол-ва категорий.
для MySQL:SELECT COUNT(*) FROM shop_categories;
для Yii-2:
Category::find()->count();результат - число, например "11"
или так:
Category::find()->select('COUNT(*) AS cnt')->asArray()->one();результат в массиве

Важно! Кол-во товаров сохраняется в создаваемое динамически свойство cnt, но в сущности Category его изначально нет. Поэтому, чтобы оно появилось в результатах выборки, его нужно добавить:
class Category extends ActiveRecord { public $cnt; …
Теперь в данное свойство можно добавлять различные значения при использовании COUNT в запросах.
Подсчет кол-ва товаров для каждого из статусов.
Например товар имеет статусы active - 1 и disabled - 0.для MySQL:
SELECT status, COUNT(*) AS cnt FROM shop_products WHERE quantity > 0 GROUP BY status

для Yii-2:
Product::find() ->select(['status', 'COUNT(*) AS cnt']) ->where(['>', 'quantity', 0]) ->groupBy('status') ->asArray() ->all();

Подсчет строк в связанной таблице.
Задача отобрать все категории с указанием количества товаров в каждой из них (связь shop_categories.id = shop_products.category_id)
для MYSQL:
SELECT shop_categories.*, COUNT(shop_products.id) cnt FROM shop_categories LEFT JOIN shop_products ON shop_categories.id = shop_products.category_id WHERE shop_categories.depth > 0 GROUP BY id ORDER BY shop_categories.lft
для Yii-2:
1. вариант (правильный) - тут используется метод joinWith для связи с таблицей products
// Связывающий метод в сущности Category public function getProduct(): ActiveQuery { return $this->hasOne(Product::class, ['category_id' => 'id']); }Пример
$categories = Category::find()->alias('c') ->select(['c.*', 'COUNT(p.id) AS cnt']) ->joinWith('product p', false) ->where(['>', 'c.depth', 0]) ->groupBy('c.id') ->orderBy('c.lft') ->all();Тут я для joinWith вторым аргументом передаю false - отключаю жадную загрузку данной таблицы (products), т.к. она не нужна, а только кол-во товаров из нее.
2. вариант - без использования joinWith, аналогично как на чистом MYSQL:
$categories = Category::find()->alias('c') ->select(['c.*', 'COUNT(p.id) AS cnt']) ->leftJoin('shop_products p', 'c.id = p.category_id') ->where(['>', 'c.depth', 0]) ->groupBy('c.id') ->orderBy('c.lft') ->all();
Подсчет строк из нескольких таблиц, суммирование результатов.
Используются 3 таблицы: shop_categories, shop_category_assignments и shop_products
Нужно подсчитать кол-во разных товаров в каждой из категорий. При этом есть 2 связи для таблицы категорий:
1. shop_products имеет прямую связь по полю "category_id";
2. shop_products имеет связь через промежуточную таблицу shop_category_assignments
В category_id указывается только одна главная категория товара, а в таблице shop_category_assignments указываются дополнительные категории.
Т.е. нужно подсчитать сколько разных товаров для каждой категории хранится в таблице shop_products и аналогично в таблице shop_category_assignments, потом эти 2 значения сложить и значение сохранить в свойстве "cnt". Параллельно нужно получить сами категории со всеми полями данной таблицы (shop_categories).
для MySQL:
SELECT shop_categories.*, (SELECT COUNT(*) FROM shop_products WHERE shop_categories.id = shop_products.category_id) + (SELECT COUNT(*) FROM shop_category_assignments WHERE shop_categories.id = shop_category_assignments.category_id) as cnt FROM shop_categories WHERE shop_categories.depth > 0 GROUP BY id ORDER BY shop_categories.lft
Для Yii2:
- используя Query Builder (получаем массивы)
$expression = "(SELECT COUNT(*) FROM shop_products AS p WHERE c.id = p.category_id) + (SELECT COUNT(*) FROM shop_category_assignments AS ca WHERE c.id = ca.category_id) as cnt"; $categories = (new Query()) ->select('c.*') ->addSelect($expression) ->from(['c' => 'shop_categories']) //алиас "c" ->where(['>', 'c.depth', 0]) ->groupBy('c.id') ->orderBy('c.lft') ->all();
- используя Active Record (получаем объекты)
$expression = "(SELECT COUNT(*) FROM shop_products AS p WHERE c.id = p.category_id) + (SELECT COUNT(*) FROM shop_category_assignments AS ca WHERE c.id = ca.category_id) as cnt"; $categories = Category::find()->alias('c') ->select('c.*') ->addSelect($expression) ->where(['>', 'c.depth', 0]) ->groupBy('c.id') ->orderBy('c.lft') ->all();
Т.к. свойства cnt, в которое будет сохраняться подсчитанное кол-во товаров у сущности (модели) Category нет, нужно предварительно создать такое публичное свойство для данного класса.