MySQL и PHP: подсчет количества товаров в категориях.
Наверное, проще показать что требуется схематически:
Категория 1 (parent=0) 20 товаров (сумма товаров в подчиненных категориях)
Категория 55 (parent=1) - 15 товаров
Категория 56 (parent=1) - 5 товаров (количество берет из подчиненной)
Категория 100 (parent=56) - 5 товаров
(тут каким то образом нужно пересчитать количество записей в таблице товаров)
Категория 3 (parent=0) - 22 товара (сумма товаров в подчиненных категориях)
Категория 5 (parent=3) - 22 товара
Категория 12 (parent=3) - товаров нет
Единственный вариант, который приходит в голову, чтобы не использовать запросы в цикле — добавить поле в таблицу категорий, и при добавлении/редактировании/удалении товаров и категорий производить пересчет: например добавили товар - прибавляем единичку категории, в которую положили товар, выбираем parent_id этой категории, обновляем количество уже этой категории и так до тех пока не достигнем parent_id=0 (корневая). С категориями при изменении "предка" делаем что то похожее - сначала ищем категорию самого низкого уровня, пересчитываем товар и рекурсивный обход до категории самого высокого уровня (parent=0).
Надеюсь не слишком сумбурно :)
1 ответов
Решил все таки сделать в админке волшебную кнопку "пересчитать товар" — добавить немного AJAX и операция не будет сильно затратной, более того эта операция снимается с пользовательской части, так как данные получается хранятся в готовом виде.
Теперь есть небольшой вопрос в знатокам Zend Framework — что то я немного не соображу с составлением запроса с помощью Zend_Db. На чистом SQL запрос выглядит так:
SELECT categories.title AS title, COUNT( * ) AS count_goods
FROM categories
LEFT JOIN goods ON goods.catId = categories.id
GROUP BY categories.id
А как это расписать используя
select()->from()->joinLeft()->group()
В mysql у Вас небольшой выбор при данной структуре хранения данных :
1. Как вы написали, добавить тригеры и пересчитывать количество при изменении данных
2.Использовать рекурсию , т.е. выполнять несколько запросов
а) на стороне клиента
б) на стороне сервера в хранимой процедуре используя курсоры.
Ну или переделать таблицу (например, неплохая статья про то, как хранить иерархические данные в БД : http://www.alandelevie.com/2008/07/12/recursion-less-storage-of-hierarchical-data-in-a-relational-database/
Т.к. дерево категорий небольшое его можно подгружать в массив и делать запрос вида:
SELECT COUNT( * ) AS count_goods FROM goods WHERE goods.category IN (1,23,52,78,199)
Т.е. в
goods.category IN (1,23,52,78,199)
вписывать все child_ID категории Parent_ID.
Кол-во запросов зависит от количества корневых котегорий.
Если заранее известна глубина вложенности, можно использовать ROLLUP. По ссылке довольно подробно все описано, есть примеры.
Если нет — только рекурсивно или циклом.