Перейти к содержимому


Фото
* * * * * 2 голосов

Категории в Компании, или логика задом наперед

модулек бренд категория здоровье счастье удобство

Best Answer Noxter , 23.07.2014 - 16:21

Мой запрос занял 0.0007 сек.  :) выглядит громоздко но выполняется быстрее представленных вариантов

 

SELECT c.id, c.name, c.url, b.url AS brand
FROM s_categories AS c
LEFT JOIN s_products_categories AS pc
ON pc.category_id = c.id
LEFT JOIN s_products AS p
ON p.id = pc.product_id
LEFT JOIN s_brands AS b
ON b.id = p.brand_id
WHERE b.id=3 
AND c.visible = 1
GROUP BY c.id
ORDER BY c.name ASC
Перейти к посту


  • Чтобы отвечать, сперва войдите на форум
20 ответов в теме

#1 ExtraBash

ExtraBash
  • Пользователь
  • 109 сообщений
  • Дизайн, Программирование, Верстка, Заказчик
  • Версия CMS:2.x
  • Откуда:Самара

Опубликовано 23.07.2014 - 00:53

Привет ребята, возникла второй раз уже необходимость сделать так,
чтобы человек зайдя в бренд, тем самым заполнив переменную $brand
мог увидеть какие категории содержит сие бренд.
 

Например: http://felicita63.ru...ds/kuppersbusch

Решил поделиться решением, возможно и не самым красивым в
плане производительности, хотя ухудшения на практике не заметил.
Решение работало в 2.24, в 2.3.5 тоже нормалек.


Первым делом добавим в низовья файла /api/Products.php

//функция позволяет узнать все категории, в которых есть товары определенной компании
    public function brands_category($bandd_id) 
        {
        $this->db->query("
            SELECT c.id, c.name, c.url, b.url AS brand
            FROM s_categories AS c
            LEFT JOIN s_products_categories AS pc
            ON pc.category_id = c.id
            LEFT JOIN s_products AS p
            ON p.id = pc.product_id
            LEFT JOIN s_brands AS b
            ON b.id = p.brand_id
            WHERE b.id=? 
            AND c.visible = 1
            GROUP BY c.id
            ORDER BY c.name ASC
        ", $bandd_id); 
        $brand_categories = $this->db->results();
        return $brand_categories;
        }    

// Спасибо за быстрый код пользователю Noxter

 

Думаю всем все ясно чего тут и куда, научились получать необходимую информацию,

опозжее сия момента произведите следующую манипуляцию с файлом /view/ProductsView.php

Примерно с 32 строки переделываем функцию в вот такую:

// Если задан бренд, выберем его из базы
if (!empty($brand_url))
{	
$brand = $this->brands->get_brand((string)$brand_url);
	if (empty($brand))
		return false;
	
	$this->design->assign('brand', $brand);
	$filter['brand_id'] = $brand->id;
	
	//Получаем категории бренда и передаем их в шаблон
	$brand_cat= $this->products->brands_category($brand->id);
	$this->design->assign('brand_cat', $brand_cat);
}

 

Собственно почти все, почти готово, имеем нужную информацию, можно пользоваться в шаблонах:

{if ($brand)}

<div class="sort companysort">
	<h2 style="margin-bottom: 10px;">Товары компании представлены в категориях</h2>
	<a href="brands/{$brand->url}{if !($smarty.server.REQUEST_URI|strstr:'brands')}&show=1{/if}"><div {if ($smarty.server.REQUEST_URI|strstr:'brands')}class="selected"{/if}>Все категории</div></a>
	{foreach $brand_cat as $bc}
		<a href="catalog/{$bc->url}/{$brand->url}"><div {if $category->url == $bc->url}class="selected"{/if}>{$bc->name}</div></a>
	{/foreach}
</div>

{/if}
Или иными, более изощренными методами, для коих у вас нынче есть инструментарий.

 

Надеюсь будет полезно, пользуйтесь на здоровье(счастье).

 

Если не поскупитесь за полезность - +7 937 204-69-07.



#2 Noxter

Noxter

    Simpla Developer

  • Фрилансер
  • 4 435 сообщений
  • Дизайн, Программирование, Верстка
  • Версия CMS:2.x
  • Откуда:Киев

Опубликовано 23.07.2014 - 00:56

Я делал такое только не таким топорным методом.

Напомните на днях напишу урок.



#3 ExtraBash

ExtraBash
  • Пользователь
  • 109 сообщений
  • Дизайн, Программирование, Верстка, Заказчик
  • Версия CMS:2.x
  • Откуда:Самара

Опубликовано 23.07.2014 - 00:59

Я делал такое только не таким топорным методом.

Напомните на днях напишу урок.

 

Ну вы то вон какой козырь острый, я и написал, что метод не из прекрасных. Заранее спасибо за прекрасный)

x_c3c194ef.jpg



#4 ExtraBash

ExtraBash
  • Пользователь
  • 109 сообщений
  • Дизайн, Программирование, Верстка, Заказчик
  • Версия CMS:2.x
  • Откуда:Самара

Опубликовано 23.07.2014 - 10:59

Метод не только "топорный", но просто таки вредительский в плане создания тормозов.

Если данных в магазине немного, но, может, и незаметно.

А с возрастанием количества товаров у бренда нагрузка будет возрастать в арифметической прогрессии.

Первый пост - характерный пример того, как НЕЛЬЗЯ делать.

 

А уж намекать на деньги за такую откровенную халтуру - совсем нехорошо...

На месте владельца серьезного магазина можно смело отдать 3000 руб, только чтобы такое НЕ устанавливать. Ибо в случае установки убытки будут куда больше...

 

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

Привет товарисч, я и написал, что все бесплатно, давайте вы сделаете все прекрасненько.
При 1800 товарах ничего не изменилось со временем построения страницы) 



#5 Kosjak76

Kosjak76
  • Модератор
  • 3 129 сообщений
  • Программирование, Верстка
  • Версия CMS:1.x, 2.x
  • Откуда:Харьков, Украина

Опубликовано 23.07.2014 - 11:08

Если не ошибаюсь, есть вариант на форуме бесплатный.

Одна функция с одним запросом.



#6 yr4ik

yr4ik
  • Фрилансер
  • 433 сообщений
  • Дизайн, Программирование, Верстка
  • Версия CMS:1.x, 2.x
  • Откуда:Украина Чернигов

Опубликовано 23.07.2014 - 15:01

Примерно так:



    //функция позволяет узнать все категории, в которых есть товары определенной компании
    public function brands_category($brand_id)
    {
    $this->db->query("SELECT DISTINCT c.id, c.name, c.url FROM s_products p, s_products_categories pc, s_categories c WHERE pc.product_id = p.id AND pc.category_id = c.id AND p.brand_id = ?", $brand_id);
    $brand_categories = $this->db->results();
    return $brand_categories;
    }	

 

Я считаю, что какой то тут не совсем правильный запрос получается... 

 

Как вариант:

"SELECT c.id, c.name, c.url FROM s_products AS p LEFT JOIN s_products_categories AS pc ON (pc.product_id=p.id) LEFT JOIN s_categories AS c ON (c.id=pc.category_id) WHERE p.brand_id = ? GROUP BY c.id"

Думаю выполнится быстрее



#7 Noxter

Noxter

    Simpla Developer

  • Фрилансер
  • 4 435 сообщений
  • Дизайн, Программирование, Верстка
  • Версия CMS:2.x
  • Откуда:Киев

Опубликовано 23.07.2014 - 15:57

Я считаю, что какой то тут не совсем правильный запрос получается... 

 

Как вариант:

"SELECT c.id, c.name, c.url FROM s_products AS p LEFT JOIN s_products_categories AS pc ON (pc.product_id=p.id) LEFT JOIN s_categories AS c ON (c.id=pc.category_id) WHERE p.brand_id = ? GROUP BY c.id"

Думаю выполнится быстрее

Я не знаю почему Вы считаете что вариант корса не правильный, но у меня вернуло как раз то что нужно для вывода категорий а именно название, ссылку и ее айди.



#8 yr4ik

yr4ik
  • Фрилансер
  • 433 сообщений
  • Дизайн, Программирование, Верстка
  • Версия CMS:1.x, 2.x
  • Откуда:Украина Чернигов

Опубликовано 23.07.2014 - 16:07

Я не говорил что результаты будут не правельным... Дело в оптимизации.

Запрос kors сгружает все строки с таблиц s_products p, s_products_categories pc, s_categories.

Затем начинает сравнение pc.product_id = p.id AND pc.category_id = c.id AND p.brand_id = ?

А после отсеивает повторы - DISTINCT

 

Тот запрос что я дал - быстрее. Он должен пройти по уже проставленным индексам и проверить только на совпадение с p.brand_id 



#9 Noxter

Noxter

    Simpla Developer

  • Фрилансер
  • 4 435 сообщений
  • Дизайн, Программирование, Верстка
  • Версия CMS:2.x
  • Откуда:Киев

Опубликовано 23.07.2014 - 16:18

Я не говорил что результаты будут не правельным... Дело в оптимизации.

Запрос kors сгружает все строки с таблиц s_products p, s_products_categories pc, s_categories.

Затем начинает сравнение pc.product_id = p.id AND pc.category_id = c.id AND p.brand_id = ?

А после отсеивает повторы - DISTINCT

 

Тот запрос что я дал - быстрее. Он должен пройти по уже проставленным индексам и проверить только на совпадение с p.brand_id 

Ваш запрос занял 0.0018 сек. в то время как запрос корса занял 0.0011 сек., проверял в phpmyadmin со стандартной базой товаров симплы.



#10 Noxter

Noxter

    Simpla Developer

  • Фрилансер
  • 4 435 сообщений
  • Дизайн, Программирование, Верстка
  • Версия CMS:2.x
  • Откуда:Киев

Опубликовано 23.07.2014 - 16:21   Best Answer

Мой запрос занял 0.0007 сек.  :) выглядит громоздко но выполняется быстрее представленных вариантов

 

SELECT c.id, c.name, c.url, b.url AS brand
FROM s_categories AS c
LEFT JOIN s_products_categories AS pc
ON pc.category_id = c.id
LEFT JOIN s_products AS p
ON p.id = pc.product_id
LEFT JOIN s_brands AS b
ON b.id = p.brand_id
WHERE b.id=3 
AND c.visible = 1
GROUP BY c.id
ORDER BY c.name ASC


#11 yr4ik

yr4ik
  • Фрилансер
  • 433 сообщений
  • Дизайн, Программирование, Верстка
  • Версия CMS:1.x, 2.x
  • Откуда:Украина Чернигов

Опубликовано 23.07.2014 - 19:03

Noxter Ну этого никак не может быть. Попробуйте через profiler. http://habrahabr.ru/post/70435/

9b81av7bpjpp5m5wm450034nzdra31fyqdzk90ku

Ну малые базы это не точно... Нужно пробовать на больших БД. Там сразу должно быть видно разницу



#12 ExtraBash

ExtraBash
  • Пользователь
  • 109 сообщений
  • Дизайн, Программирование, Верстка, Заказчик
  • Версия CMS:2.x
  • Откуда:Самара

Опубликовано 23.07.2014 - 21:42

Мой запрос занял 0.0007 сек.  :) выглядит громоздко но выполняется быстрее представленных вариантов

 

 

SELECT c.id, c.name, c.url, b.url AS brand
FROM s_categories AS c
LEFT JOIN s_products_categories AS pc
ON pc.category_id = c.id
LEFT JOIN s_products AS p
ON p.id = pc.product_id
LEFT JOIN s_brands AS b
ON b.id = p.brand_id
WHERE b.id=3 
AND c.visible = 1
GROUP BY c.id
ORDER BY c.name ASC

 

Ребята, красота, блеск, шик.
Вот этот вариант действительно быстрее всех, мой самый по бичу.

 

Ваши различаются очень мало, но этот стабильно быстрее строит конечную страничку.

Закину этот вариант в инструкцию?
Про оплату уберу.



#13 Kors

Kors
  • Фрилансер
  • 2 918 сообщений
  • Программирование
  • Версия CMS:1.x, 2.x
  • Откуда:Россия

Опубликовано 24.07.2014 - 07:54

Если заменить LEFT JOIN на INNER JOIN, то запрос должен стать еще легче.

LEFT JOIN s_brands AS b - также можно удалить для облегчения

#14 Noxter

Noxter

    Simpla Developer

  • Фрилансер
  • 4 435 сообщений
  • Дизайн, Программирование, Верстка
  • Версия CMS:2.x
  • Откуда:Киев

Опубликовано 24.07.2014 - 15:35

Noxter Ну этого никак не может быть. Попробуйте через profiler. http://habrahabr.ru/post/70435/
Ну малые базы это не точно... Нужно пробовать на больших БД. Там сразу должно быть видно разницу

 

Чего не может быть? Если Вы о скорости, то прочтите мое сообщение еще раз в котором я четко написал:

Ваш запрос занял 0.0018 сек. в то время как запрос корса занял 0.0011 сек., проверял в phpmyadmin со стандартной базой товаров симплы.

 

Вы для начала протестируйте все 3 запроса в phpmyadmin как это сделал я, а уж потом спорьте.



#15 yr4ik

yr4ik
  • Фрилансер
  • 433 сообщений
  • Дизайн, Программирование, Верстка
  • Версия CMS:1.x, 2.x
  • Откуда:Украина Чернигов

Опубликовано 24.07.2014 - 17:26

Я ж и протестировал! 1-корс 2-мой 3-ваш
И выложил скрин теста. Где сам себвер БД сказал что и как выполняется..
phpmyadmin в этом деле - не точный. Поскольку он возвращает результат за сколько выполнялось все. От вызова функции до получения результата. А я выложил прямые результаты с самого сервера БД
 

Если заменить LEFT JOIN на INNER JOIN, то запрос должен стать еще легче.

LEFT JOIN s_brands AS b - также можно удалить для облегчения

На счет INNER - согласен. Возможно даже лучше будет...

#16 cernos

cernos
  • Фрилансер
  • 357 сообщений
  • Дизайн, Программирование, Верстка, Заказчик
  • Версия CMS:2.x
  • Откуда:Донецк

Опубликовано 19.09.2014 - 02:55

Полезно иной раз полистать и эту ветку форума. Полезная фича, взял на заметку для своего любимого магазинчика.



#17 cernos

cernos
  • Фрилансер
  • 357 сообщений
  • Дизайн, Программирование, Верстка, Заказчик
  • Версия CMS:2.x
  • Откуда:Донецк

Опубликовано 21.09.2014 - 21:47

Запрос для тех, кому нужно сделать вывод количества товаров бренда в категории:

SELECT c.id, c.name, c.url, b.url AS brand, count(p.id) as `products`
FROM s_categories AS c
INNER JOIN s_products_categories AS pc
ON pc.category_id = c.id
INNER JOIN s_products AS p
ON p.id = pc.product_id
INNER JOIN s_brands AS b
ON b.id = p.brand_id
WHERE b.id=3 
AND c.visible = 1
GROUP BY c.id
ORDER BY c.name ASC

Результат находится в ячейке products

 

PS: доработанный запрос от Noxter



#18 Noxter

Noxter

    Simpla Developer

  • Фрилансер
  • 4 435 сообщений
  • Дизайн, Программирование, Верстка
  • Версия CMS:2.x
  • Откуда:Киев

Опубликовано 22.09.2014 - 02:18

:)

#19 crab

crab
  • Пользователь
  • 16 сообщений

Опубликовано 09.04.2016 - 15:25

Вставил код в /api/Products.php

 

на локальном сервере выдает ошибку

 

Parse error: syntax error, unexpected T_PUBLIC in Z:\home\localhost\www\site\api\Products.php on line 549


Изменено: crab, 09.04.2016 - 15:26


#20 Kors

Kors
  • Фрилансер
  • 2 918 сообщений
  • Программирование
  • Версия CMS:1.x, 2.x
  • Откуда:Россия

Опубликовано 09.04.2016 - 16:45

Видимо, вставил код не тот. Или не в то место вставил.

Для Вас написано сообщение об ошибке, расшифровано так, что понятнее уже некуда.

Можно предположить, что вставили в самый конец, а надо перед финальной скобкой "}"...







Также с меткой «модулек, бренд, категория, здоровье, счастье, удобство»

0 пользователей читают эту тему

0 пользователей, 0 гостей, 0 скрытых