Это для MySQL и PHP
У меня есть таблица, которая содержит следующие столбцы:
navigation_id (unsigned int primary key)
navigation_category (unsigned int)
navigation_path (varchar (256))
navigation_is_active (bool)
navigation_store_id (unsigned int index)
Данные будут заполнены как:
1, 32, "4/32/", 1, 32
2, 33, "4/32/33/", 1, 32
3, 34, "4/32/33/34/", 1, 32
4, 35, "4/32/33/35/", 1, 32
5, 36, "4/32/33/36/", 1, 32
6, 37, "4/37/", 1, 32
... another group that is under the "4/37" node
... and so on
Так что это будет представлять собой древовидную структуру. Моя цель - написать SQL-запрос, который с учетом идентификатора магазина 32 и идентификатора категории 33 вернет
Во-первых, группа элементов, которые являются родителями категории 33 (в данном случае 4 и 32)
Затем группа элементов, которые являются дочерними для категории 33 (в данном случае 34, 35 и 36)
Тогда остальные «корневые» категории категории 4 (в данном случае 37).
Таким образом, следующий запрос вернет правильные результаты:
SELECT * FROM navigation
WHERE navigation_store_id = 32
AND (navigation_category IN (4, 32)
OR navigation_path LIKE "4/32/33/%/"
OR (navigation_path LIKE "4/%/"
AND navigation_category <> 32))
Моя проблема заключается в том, что я хочу упорядочить «группы» категорий в указанном выше порядке (родители в возрасте 33 года, дети в возрасте 33 года и родители корневого узла в последнюю очередь). Поэтому, если они соответствуют первому условию, закажите их первым, если они соответствуют второму условию, закажите их вторым, и если они соответствуют третьему (и четвертому) условию, закажите их последним.
Вы можете увидеть пример того, как работает структура категорий на этом сайте:
www.eanacortes.net
Вы можете заметить, что это довольно медленно. Текущий способ, которым я делаю это, я использую исходную таблицу категорий magento и выполняю три особенно медленных запроса к ней; затем положить результаты вместе в PHP. Используя эту новую таблицу, я решаю еще одну проблему, связанную с magento, но в то же время я хотел бы улучшить свою производительность. Лучший способ добиться этого - соединить все три запроса и заставить PHP работать меньше, если результаты отсортированы правильно.
Спасибо
EDIT
Хорошо, теперь это прекрасно работает. Сократите его с 4 секунд до 500 мс. Большая скорость сейчас:)
Вот мой код в классе Colleciton:
function addCategoryFilter($cat)
{
$path = $cat->getPath();
$select = $this->getSelect();
$id = $cat->getId();
$root = Mage::app()->getStore()->getRootCategoryId();
$commaPath = implode(", ", explode("/", $path));
$where = new Zend_Db_Expr(
"(navigation_category IN ({$commaPath})
OR navigation_parent = {$id}
OR (navigation_parent = {$root}
AND navigation_category <> {$cat->getId()}))");
$order = new Zend_Db_Expr("
CASE
WHEN navigation_category IN ({$commaPath}) THEN 1
WHEN navigation_parent = {$id} THEN 2
ELSE 3
END, LENGTH(navigation_path), navigation_name");
$select->where($where)->order($order);
return $this;
}
Затем я использую следующий код, найденный в моем блоке категорий:
// get our data
$navigation = Mage::getModel("navigation/navigation")->getCollection();
$navigation->
addStoreFilter(Mage::app()->getStore()->getId())->
addCategoryFilter($currentCat);
// put it in an array
$node = &$tree;
$navArray = array();
foreach ($navigation as $cat)
{
$navArray[] = $cat;
}
$navCount = count($navArray);
$i = 0;
// skip passed the root category
for (; $i < $navCount; $i++)
{
if ($navArray[$i]->getNavigationCategory() == $root)
{
$i++;
break;
}
}
// add the parents of the current category
for (; $i < $navCount; $i++)
{
$cat = $navArray[$i];
$node[] = array("cat" => $cat, "children" => array(),
"selected" => ($cat->getNavigationCategory() == $currentCat->getId()));
$node = &$node[0]["children"];
if ($cat->getNavigationCategory() == $currentCat->getId())
{
$i++;
break;
}
}
// add the children of the current category
for (; $i < $navCount; $i++)
{
$cat = $navArray[$i];
$path = explode("/", $cat->getNavigationPath());
if ($path[count($path) - 3] != $currentCat->getId())
{
break;
}
$node[] = array("cat" => $cat, "children" => array(),
"selected" => ($cat->getNavigationCategory() == $currentCat->getId()));
}
// add the children of the root category
for (; $i < $navCount; $i++)
{
$cat = $navArray[$i];
$tree[] = array("cat" => $cat, "children" => array(),
"selected" => ($cat->getNavigationCategory() == $currentCat->getId()));
}
return $tree;
Если бы я мог принять два ответа, я бы принял первый и последний, и если бы я мог принять ответ как "интересный / полезный", я бы сделал это со вторым.
:)