Перейти до вмісту
Пошук в
  • Детальніше...
Шукати результати, які ...
Шукати результати в ...

Последних N товаров из категорий одним запросом


Recommended Posts

Я не силен в MySql и рекурсии, может уважаемые гуру помогут реализовать сабж.

В идеале хочется получить последние N товаров из каждой категории.

Надіслати
Поділитися на інших сайтах

Нужны последние добавленные.

Критерием отбора может быть дата добавления или на худой конец id товара.

 

С рекурсией я наверное погорячился, скорее я имел в виду вложенные селекты и т.п.

Надіслати
Поділитися на інших сайтах

22 минуты назад, nikifalex сказал:

я бы не советовал делать это одним запросом.

лучше и быстрее на php 

 

Хотелось бы услышать аргументы на счет нежелательности одного запроса.


На PHP лучше и быстрее в смысле проще программировать или работать будет быстрее?
Если в магазине больше сотни категорий, то не хочется создавать столько же лишних запросов.

По этому и ищу нечто подобное:

SET @I=0; 
SET @C='';
SELECT ID, Name, Category FROM (
    SELECT B.*, 
    IF(@C != B.Category, @I:=1, @I:=@I+1) AS RowNum,
    @C:=B.Category
    FROM (
        SELECT ID, Name, Category FROM Products GROUP BY Name, Category ORDER BY Category
    ) AS B HAVING RowNum <= 2
) AS A

Но в данном примере все поля лежат в одной таблице.
Помогите грамотно сделать join таблиц product_to_category и  product_description.

Надіслати
Поділитися на інших сайтах

 

SELECT p.* ,pd.* FROM `oc_product` p 
	LEFT JOIN `oc_product_description` pd ON (p.`product_id` = pd.`product_id`)
	LEFT JOIN `oc_product_to_category` p2c ON (p.`product_id` = p2c.`product_id`) 
	WHERE p2c.`category_id` IN (20,26,27) AND p.`status` = 1 AND (p.`date_available` <= NOW()) AND (p.`date_added` > DATE_SUB(NOW(),INTERVAL 60 DAY)) GROUP BY p.`product_id`

- изменить только на свой префикс в таблицах (oc_)

- p2c.`category_id` IN (20,26,27) - id категорий (если все нужны - их можно получить доп.зпросом)

- INTERVAL 60 DAY - количество дней, при котором будут считаться товары последне-добавленные.

Надіслати
Поділитися на інших сайтах

в том-то и дело, что по десять из каждой
А кортеж будет толко из десяти
можно сгенерить 1 запрос с 100 UNION по 10

 

Надіслати
Поділитися на інших сайтах

SET @I=0; 
SET @C='';
SELECT ID, Name, Category FROM (
    SELECT B.*, 
    IF(@C != B.Category, @I:=1, @I:=@I+1) AS RowNum,
    @C:=B.Category
    FROM (
        SELECT p.product_id ID, pd.name Name, p2c.category_id Category
		FROM oc_product p
		LEFT JOIN oc_product_description pd ON p.product_id = pd.product_id
		LEFT JOIN oc_product_to_category p2c ON p2c.product_id =  p.product_id
		WHERE pd.language_id = 1
		
		
		GROUP BY pd.name, p2c.category_id ORDER BY p2c.category_id
    ) AS B HAVING RowNum <= 10
) AS A

Но я бы все рано это делал бы отдельными запросами

 

Надіслати
Поділитися на інших сайтах

12 часов назад, vier сказал:

- изменить только на свой префикс в таблицах (oc_)

- p2c.`category_id` IN (20,26,27) - id категорий (если все нужны - их можно получить доп.зпросом)

- INTERVAL 60 DAY - количество дней, при котором будут считаться товары последне-добавленные.


Спасибо за совет, но ваш запрос получает все данные за 60 дней из указаных категорий, но не решает проблему заданных N товаров.
 

Надіслати
Поділитися на інших сайтах

3 часа назад, nikifalex сказал:

потому что mysql это вам не mssql

ему лучше 100 запросов с которыми он знает что делать, чем один крупный

не факт

 

Надіслати
Поділитися на інших сайтах

 

@chukcha

Спасибо, запрос действительно получает по 3 товара из каждой категории, но к сожалению это не последние товары.
Не подскажете как правильно сделать группировку по product_id, чтобы получить последние?
Мой текущий запрос (добавлено условие на главную категорию os_store):

SET @I=0; 
SET @C='';
SELECT * FROM (
    SELECT B.*, 
    IF(@C != B.category_id, @I:=1, @I:=@I+1) AS RowNum,
    @C:=B.category_id
    FROM (
        SELECT p.product_id, pd.name, p2c.category_id, p2c.main_category, cd.name cname
		FROM oc_product p
		LEFT JOIN oc_product_description pd ON pd.product_id = p.product_id
		LEFT JOIN oc_product_to_category p2c ON p2c.product_id = p.product_id
		LEFT JOIN oc_category_description cd ON p2c.category_id = cd.category_id
		WHERE p2c.main_category = 1
		GROUP BY p2c.product_id, p2c.category_id ORDER BY p2c.category_id DESC
    ) AS B HAVING RowNum <= 4
) AS A

 

Надіслати
Поділитися на інших сайтах

12 часов назад, chukcha сказал:

Но я бы все рано это делал бы отдельными запросами


С учетом того, что категорий сотни полторы, то не хотелось бы генерить столько же запросов в цикле.
Как по вашему, какое решение было бы оптимально?

Надіслати
Поділитися на інших сайтах

1 минуту назад, Wild сказал:

С учетом того, что категорий сотни полторы, то не хотелось бы генерить столько же запросов в цикле.
Как по вашему, какое решение было бы оптимально?

 

4 часа назад, nikifalex сказал:

результат конечно кэшируйте если не хотите много запросов каждый раз

 

Надіслати
Поділитися на інших сайтах

4 минуты назад, Wild сказал:

но к сожалению это не последние товары.

т.е. вы хотели чтобы я вам привел полный запрос?

 

 

2 минуты назад, Wild сказал:

Как по вашему, какое решение было бы оптимально?

надо смотреть  план выполнения, время и прочее

Т.е. если при одиночных запросах вы может иметь оптимизированные запросы
то в данном случае вы получите fuulscan и непонятное поведение сервера

Надіслати
Поділитися на інших сайтах

9 минут назад, Wild сказал:

Не подскажете как правильно сделать группировку по product_id, чтобы получить последние?


По ходу эта группировка решает проблему:
 

GROUP BY p2c.category_id, p2c.product_id ORDER BY p2c.category_id, p2c.product_id DESC

 

Надіслати
Поділитися на інших сайтах

3 минуты назад, Wild сказал:

По ходу эта группировка решает проблему:

нет не решает

Надіслати
Поділитися на інших сайтах

4 минуты назад, chukcha сказал:

т.е. вы хотели чтобы я вам привел полный запрос?

Я просто спросил совета.
В любом случае ОГРОМНОЕ спасибо вам.

 

4 минуты назад, chukcha сказал:

надо смотреть  план выполнения, время и прочее
Т.е. если при одиночных запросах вы может иметь оптимизированные запросы
то в данном случае вы получите fuulscan и непонятное поведение сервера

Ну да, три вложенных select'а...
Но вроде отрабатывает нормально.

Надіслати
Поділитися на інших сайтах

вложенность это не показатель

 

SELECT p.product_id, pd.name, p2c.category_id, p2c.main_category, cd.name cname
		FROM oc_product p
		LEFT JOIN oc_product_description pd ON pd.product_id = p.product_id
		LEFT JOIN oc_product_to_category p2c ON p2c.product_id = p.product_id
		LEFT JOIN oc_category_description cd ON p2c.category_id = cd.category_id
		WHERE p2c.main_category = 1
		GROUP BY p2c.product_id, p2c.category_id ORDER BY p2c.category_id DESC

Здесь вы получаете фулскан, хотя и ограничиваете  главной категорией

Т.е. рл сути это и есть самый тормоз

Далее ваш подзапрос, возможно, поместится в память, и выборка из него уже будет быстрой

можно убрать связку по языку, добавить по статусу, т.е.  еще упростить и уменьшить..


 

Надіслати
Поділитися на інших сайтах

5 минут назад, Wild сказал:

Перепроверил, данные вроде сходятся.

В чем могут возникнуть грабли?

потому что это случайность что product_id ~ date_add

Надіслати
Поділитися на інших сайтах

24 минуты назад, chukcha сказал:

потому что это случайность что product_id ~ date_add

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

31 минуту назад, chukcha сказал:

вложенность это не показатель
Здесь вы получаете фулскан, хотя и ограничиваете  главной категорией
Т.е. рл сути это и есть самый тормоз
Далее ваш подзапрос, возможно, поместится в память, и выборка из него уже будет быстрой

можно убрать связку по языку, добавить по статусу, т.е.  еще упростить и уменьшить..

Да, теперь есть куда улучшать и оптимизировать.

Надіслати
Поділитися на інших сайтах

2 часа назад, Wild сказал:

Спасибо за совет, но ваш запрос получает все данные за 60 дней из указаных категорий, но не решает проблему заданных N товаров.

а кто Вам мешает добавить еще одно поле для выборки - p2c.`category_id` (я вообще бы рекомендовал указывать только нужные поля для обработки, а не использовать звездочку - * ),

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

Надіслати
Поділитися на інших сайтах

4 часа назад, vier сказал:

а кто Вам мешает добавить еще одно поле для выборки - p2c.`category_id` (я вообще бы рекомендовал указывать только нужные поля для обработки, а не использовать звездочку - * ),

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

 

Звездочку юзаю только на этапе отладки, чтобы видеть что выбирается и джойнится.

Сategory_id в приведенном вами примере и так есть, а толку?
Задачу не решает.

Про цикл уже писал, не хочется лишних 150 запросов.

Надіслати
Поділитися на інших сайтах

32 минуты назад, Wild сказал:

Про цикл уже писал, не хочется лишних 150 запросов.

так цикл не в запросе к базе, а после получения результата (одного запроса).

$results;// - полученный результат.
$data['products'] = array();//сюда результат запишем
$count_cat = array();//временная переменная
$n = 10;//ограничение по количеству
foreach($results as $colum) {
	if(isset($count_cat[$colum['category_id']])) {
		$count_cat[$colum['category_id']] = $count_cat[$colum['category_id']] + 1;
	}
	else {
		$count_cat[$colum['category_id']] = 1;
	}
	if($count_cat[$colum['category_id']] <= $n) {
		//пишем результат
		$data['products'][] = array(
		   'product_id'  => $colum['product_id'],
		   //..........
		);
	}
}

 

Надіслати
Поділитися на інших сайтах

6 минут назад, vier сказал:

$data['products'] = array();//сюда результат запишем

т.е. вы предлагаете выбрать "все" товары?
а потом разобрать результат?

А если есть категории где товары не добавлялись год?

поэту приведенный ТС запрос, и модифицированый мною - как раз и выберет по N товаров из каждой категории по дате ( в его случае по product_id)

Надіслати
Поділитися на інших сайтах

Створіть аккаунт або увійдіть для коментування

Ви повинні бути користувачем, щоб залишити коментар

Створити обліковий запис

Зареєструйтеся для отримання облікового запису. Це просто!

Зареєструвати аккаунт

Вхід

Уже зареєстровані? Увійдіть тут.

Вхід зараз
  • Зараз на сторінці   0 користувачів

    • Ні користувачів, які переглядиють цю сторінку
×
×
  • Створити...

Important Information

На нашому сайті використовуються файли cookie і відбувається обробка деяких персональних даних користувачів, щоб поліпшити користувальницький інтерфейс. Щоб дізнатися для чого і які персональні дані ми обробляємо перейдіть за посиланням . Якщо Ви натиснете «Я даю згоду», це означає, що Ви розумієте і приймаєте всі умови, зазначені в цьому Повідомленні про конфіденційність.