powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / MySQL [игнор отключен] [закрыт для гостей] / выборка N произвольных товаров, но не более одного для каждого поставщика
12 сообщений из 12, страница 1 из 1
выборка N произвольных товаров, но не более одного для каждого поставщика
    #38409183
despicable me
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть таблица с поставщиками, например
Код: sql
1.
2.
3.
4.
5.
6.
CREATE TABLE `companies` (
	`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
	`name` varchar(255) NOT NULL,
	`blocked` tinyint(1) NOT NULL DEFAULT '0',
	PRIMARY KEY (`id`)
);


Есть таблица с товарами, например
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
CREATE TABLE `products` (
	`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
	`company` int(11) unsigned NOT NULL,
	`name` varchar(255) COLLATE utf8_bin NOT NULL,
	`price` varchar(15) CHARACTER SET utf8 NOT NULL DEFAULT '',
	PRIMARY KEY (`id`),
	KEY `company` (`company`)
);



Необходимо сделать выборку N произвольных товаров, но не более одного для каждой компании.
...
Рейтинг: 0 / 0
выборка N произвольных товаров, но не более одного для каждого поставщика
    #38409187
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
despicable me,

в 2 этапа:
1)выбрать N произвольных компаний
2)выбрать для каждой из них по 1 товару
...
N)PROFIT!!
...
Рейтинг: 0 / 0
выборка N произвольных товаров, но не более одного для каждого поставщика
    #38416245
despicable me
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Для выборки одного случайного наименования продукции сделал следующим образом
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
SELECT * FROM (
	SELECT P.name AS product_name, P.price AS product_price, C.id AS company_id, C.name AS company_name
	FROM companies C
	INNER JOIN products P ON C.id = P.company
	WHERE C.id IN (1,2,3,...)
	ORDER BY RAND()
) AS random_products
GROUP BY company_id
LIMIT 10


Набор компаний для WHERE ... IN ... формируется отдельным запросом.
Но если необходимо сделать выборку N случайных наименований, этот способ уже не годится.
...
Рейтинг: 0 / 0
выборка N произвольных товаров, но не более одного для каждого поставщика
    #38416259
despicable me
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В общем, после продолжительных мытарств пришёл к следующему:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
SELECT product_id, product_name, product_price, company_id, company_name
FROM (
   SELECT *, @num := IF(@company = company_id, @num + 1, 1) AS row_number, @company := company_id AS dummy
   FROM (
       SELECT P.id AS product_id, P.name AS product_name, P.price AS product_price, P.company AS company_id, C.name AS company_name
       FROM products P
       LEFT JOIN companies C ON C.id = P.company
       ORDER BY P.company, RAND()
   ) AS t1
) AS t2
WHERE t2.row_number <= /*N*/
ORDER BY RAND()
LIMIT /*M*/


Где /*N*/ - количество уникальных товаров на одну компанию, /*M*/ - общее количество товаров в выборке.

Может кому будет полезно.
...
Рейтинг: 0 / 0
выборка N произвольных товаров, но не более одного для каждого поставщика
    #38416260
despicable me
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да, чуть не забыл, запросу должна предшествовать инициализация переменных:
Код: sql
1.
SET @num := 0, @company := 0
...
Рейтинг: 0 / 0
выборка N произвольных товаров, но не более одного для каждого поставщика
    #38416284
Arhat109
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
despicable me,

Не понял.

1. Почему во внутреннем джойне используется левый джойн? Есть продукция, не привязанная ни к какой компании?

2. Каков смысл order by rand() в нем же, если ограничение выборки стоит во внешнем запросе? Насколько понимаю, если у компании более одной товарной строки - это никак не мешает попасть в выдачу, хотя у Вас условие "не более одной продукции для одной компании".

3. Нумерация в таком виде - работать НЕ будет. После order by rand() - повтор номера компании через пару строчек - практически гарантирован.
...
Рейтинг: 0 / 0
выборка N произвольных товаров, но не более одного для каждого поставщика
    #38416457
Cygapb-007
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Недавно была тема Нужно что-то лучшее

По мотивам:
repro
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
CREATE TABLE `companies` (
  `cid` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `cname` varchar(255) NOT NULL,
  `cblocked` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`cid`)
)COLLATE utf8_bin;

INSERT `companies`(`cname`) VALUES
  ('comp1'),('comp2'),('comp3'),('comp4'),('comp5');

CREATE TABLE `products` (
  `pid` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `pcompany` int(11) unsigned NOT NULL,
  `pname` varchar(255) COLLATE utf8_bin NOT NULL,
  `pprice` varchar(15) CHARACTER SET utf8 NOT NULL DEFAULT '',
  PRIMARY KEY (`pid`),
  KEY `company` (`pcompany`)
) COLLATE utf8_bin;

INSERT `products`(`pcompany`,`pname`) VALUES
  (1,'prod11'),(1,'prod12'),(1,'prod13'),(1,'prod14'),(1,'prod15'),(1,'prod16'),(1,'prod17'),(1,'prod18'),
  (2,'prod21'),(2,'prod22'),(2,'prod23'),(2,'prod24'),(2,'prod25'),(2,'prod26'),
  (3,'prod31'),(5,'prod51'),(5,'prod52');


Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
select * 
from (
  select c.*, l.*,
  substring_index(
      substring_index(
        concat(',',l.pids,',')
        ,','
        ,(round(rand()*l.qty,0)mod l.qty)+2
      ),',',-1)random_id
  from companies c
  left join (
    select l.pcompany, group_concat(l.pid)pids, count(*) qty
    from products l
    group by l.pcompany
    )l on l.pcompany=c.cid
  )c
left join products p on p.pid=c.random_id;


результатыCID CNAME CBLOCKED PCOMPANY PIDS QTY RANDOM_ID PID PNAME PPRICE1 comp1 0 1 1;2;3;4;5;6;7;8 8 4 4 prod14 2 comp2 0 2 9;10;11;12;13;14 6 11 11 prod23 3 comp3 0 3 15 1 15 15 prod31 4 comp4 0 (null) (null) (null) (null) (null) (null) (null)5 comp5 0 5 16;17 2 17 17 prod52

CID CNAME CBLOCKED PCOMPANY PIDS QTY RANDOM_ID PID PNAME PPRICE1 comp1 0 1 1;2;3;4;5;6;7;8 8 2 2 prod12 2 comp2 0 2 9;10;11;12;13;14 6 12 12 prod24 3 comp3 0 3 15 1 15 15 prod31 4 comp4 0 (null) (null) (null) (null) (null) (null) (null)5 comp5 0 5 16;17 2 16 16 prod51
...
Рейтинг: 0 / 0
выборка N произвольных товаров, но не более одного для каждого поставщика
    #38416459
Cygapb-007
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
забыл про тестовую зону :) http://sqlfiddle.com/#!2/fafaba/28
...
Рейтинг: 0 / 0
выборка N произвольных товаров, но не более одного для каждого поставщика
    #38417232
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
despicable meДля выборки одного случайного наименования продукции сделал следующим образом

Но если необходимо сделать выборку N случайных наименований, этот способ уже не годится.

Так ты уж определись, СЛУЧАЙНЫХ или ПРОИЗВОЛЬНЫХ.
Разные вещи немного.
...
Рейтинг: 0 / 0
выборка N произвольных товаров, но не более одного для каждого поставщика
    #38422165
despicable me
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Arhat1091. Почему во внутреннем джойне используется левый джойн? Есть продукция, не привязанная ни к какой компании?
Теоретически - а вдруг. У меня такая привычка сложилась.

Arhat1092. Каков смысл order by rand() в нем же, если ограничение выборки стоит во внешнем запросе? Насколько понимаю, если у компании более одной товарной строки - это никак не мешает попасть в выдачу, хотя у Вас условие "не более одной продукции для одной компании".
Условие уже расширилось до N. Пробовал без внутреннего ORDER BY RAND(), но мне показалось, что это даёт дополнительную "рандомность".

Arhat1093. Нумерация в таком виде - работать НЕ будет. После order by rand() - повтор номера компании через пару строчек - практически гарантирован.
Честно, не сильно вдавался в детали. Результат меня устроил, на том пока и успокоился.
...
Рейтинг: 0 / 0
выборка N произвольных товаров, но не более одного для каждого поставщика
    #38422169
despicable me
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZivТак ты уж определись, СЛУЧАЙНЫХ или ПРОИЗВОЛЬНЫХ.
Разные вещи немного.
Так а в чём разница то в контексте описанной задачи? Случайные/произвольные из числа имеющихся.
...
Рейтинг: 0 / 0
выборка N произвольных товаров, но не более одного для каждого поставщика
    #38422383
Cygapb-007
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
despicable meMasterZivТак ты уж определись, СЛУЧАЙНЫХ или ПРОИЗВОЛЬНЫХ.
Разные вещи немного.
Так а в чём разница то в контексте описанной задачи? Случайные/произвольные из числа имеющихся.Существенная разница.

Произвольные - например, первая запись из возвращаемых сервером. Не всегда, но достаточно постоянно будет выдаваться одна и та же запись (в условиях одного запроса зависит от способа хранения и параллельных запросов на обновление данных, а так же от параллелизма выборки)

Случайные - из всего подмножества строк случайным образом выбрать одну конкретную
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / MySQL [игнор отключен] [закрыт для гостей] / выборка N произвольных товаров, но не более одного для каждого поставщика
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]