Довольно похоже на MYSQL – выберите первые 4 записи для каждой категории в таблице, но ответа нет, и один ответ там не имеет большого смысла, поэтому я снова спрашиваю.
У меня есть таблица PRODUCTS
с тремя столбцами: ID
, NAME
и CATEGORY
Теперь я хотел бы узнать, возможно ли вообще выбрать 2 продукта для каждой отдельной категории, не делая запросов в петле PHP.
Порядок выбранных продуктов не имеет значения, они также могут быть случайными. Но важно, чтобы у меня было всего 2 продукта для каждой категории.
Таким образом, хорошим результатом будет
ID ; NAME ; CATEGORY ::::::::::::::::::::::: 152 ; APPLE ; FRUIT 185 ; ORANGE ; FRUIT 145 ; BEEF ; MEAT 141 ; PORK ; MEAT 410 ; PEPSI ; DRINKS 585 ; CARROT ; VEGETABLES 585 ; TOMATO ; VEGETABLES
Что-то в этом направлении будет работать:
SELECT id, name, category FROM ( SELECT *, IF( @prev <> category, @rownum := 1, @rownum := @rownum+1 ) AS rank, @prev := category, @rownum FROM ( SELECT * FROM products ORDER BY category, rand() ) random_prodcts ) products_ranked WHERE rank <= 2;
Он упорядочивает их случайным образом в категориях, затем вытаскивает их, отслеживая, сколько из них получено.
Не уверен, насколько хорошо он будет масштабироваться.
EDIT: Пробовал несколько тысяч записей, и все выглядит нормально.
Это должно делать то, что вы ищете.
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
FULL SQL:
SELECT t.id, t.name, t.category FROM the_table AS t , (SELECT MIN(id) AS id_min FROM the_table GROUP BY category) AS t1 , (SELECT MAX(id) AS id_max FROM the_table GROUP BY category) AS t2 WHERE (t.id=t1.id_min) OR (t.id=t2.id_max)
Запрос выбирает min и max каждой категории и возвращает оба из них (или только один, если он одинаковый).
Вы сказали: «Порядок выбранных продуктов не имеет значения, они могут быть случайными», поэтому этот метод должен быть в порядке.