выборка из трёх таблиц с GROUP BY и ORDER BY

261
17 февраля 2018, 20:37

магазин с категориями товаров

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

есть три таблицы:

категории:

cats
id,name,popularity

товары:

items
id,name,popularity

таблица связей:

cats2items
cat_id, item_id

на выходе нужно получить вроде:

cat_id   item_id
1          5
3          1
2          56
10         177

мильон вариантов перепробовал, вот последний:

SELECT cats2items.cat_id, i.item_id
FROM cats2items
 inner join (
  select items.id, items.popularity
  FROM items
  ORDER by items.popularity DESC
  ) i
WHERE cats2items.item_id = i.id
AND cats2items.cat_id IN (SELECT cats.id FROM cats ORDER BY cats.popularity DESC)
GROUP BY cats2items.cat_id

но товары получаются не уникальными и они не отсортированы по популярности:

cat_id   item_id
1          86
2          3
3          1
4          49
5          3

подскажите куда копать плиз

Answer 1

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

select cat_id, cat_name, item_id, item_name
  from (
    select y.*,
           @cgrp,
           @first:=if(@cgrp!=cat_id and find_in_set(item_id,@used)=0,1,0) first,
           @used:=concat(@used,if(@first,concat(',',item_id),'')),
           @cgrp:=if(@first,cat_id,@cgrp)
      from (
        select c.id cat_id,c.name cat_name, c.popularity cat_p, i.id item_id, i.name item_name, i.popularity item_p
          from cats c, items i, cats2items ci, (select @cgrp:=0,@used:='',@first:=0) x
         where ci.cat_id=c.id and ci.item_id=i.id
         order by c.popularity desc, c.id, i.popularity desc
      ) y
  ) z
 where first=1
 order by cat_p desc, item_p desc

Пример на sqlfiddle.com. Обратите внимание, в категории 4 запрос не вывел ни одной строки, так как оба товара, которые есть в этой категории, ранее уже были выведены в других категориях. И это не лечится при данной постановке задачи, категории в которых мало товаров могут этим страдать.

READ ALSO
Индексы PRIMARY и UNIQUE KEY для одного и того же поля

Индексы PRIMARY и UNIQUE KEY для одного и того же поля

Есть ли какой-либо смысл в следующем построении индексов?

202
Создание запроса в базу на SQL, без PHP

Создание запроса в базу на SQL, без PHP

Доброго времени сутокПодскажите пожалуйста, возможно ли реализовать данный код только на SQL, минуя PHP? В таблице data имеется поле (email_disp), которое...

186
mysql не пускает через phpadmin, но в сам mysql дает

mysql не пускает через phpadmin, но в сам mysql дает

суть проблемы - стоит связка mysql/apache/php работало до вчерашнего дня лет 10при заходе на phpadmin под рутом не пускает без указания ошибки

174