SQL получает два элемента из последних четырех наборов - PullRequest
0 голосов
/ 01 ноября 2011

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

У меня есть две таблицы (InnoDB), одна для наборов изображений, которая имеет одну строку на набор с некоторой информацией, такой как set_title, с каким продуктом она связана, на /автономный статус и дата добавлены:

GallerySets

  • set_id (основной)
  • product_id (внешний ключ)
  • set_title (varchar 128)
  • set_status (перечисление онлайн / офлайн, индекс)
  • set_dateadded (datetime, index)

И таблица для отдельных изображений, каждый набор имеетодно или несколько изображений.Хотя поля пути нет, я просто использую его вроде set_id / pic_id.jpg ... Есть и другие поля, такие как viewcounts и т. Д., Но они не нужны для этой проблемы, поэтому я их пропустил.

GalleryPics

  • pic_id (основной)
  • set_id (основной, внешний ключ)
  • pic_dateadded (datetime, index)

В основном я хочу показать 2 изображения для последних 4 комплектов.У меня есть этот запрос ниже, который приближается к тому, что я хочу, единственное, что он не делает, это ограничивает его до 2 на набор:

SELECT s.`set_id`, s.`set_title`, s.`set_dateadded`, p.`pic_id`, p.`pic_dateadded`
FROM `GallerySets` s
LEFT JOIN `GalleryPics` p
ON (s.`set_id` = p.`set_id`)
WHERE s.set_status = 'online'
ORDER BY s.`set_dateadded` DESC, p.`pic_dateadded` ASC

Он просто показывает все, конечно.В других вопросах (например, этот ) я видел, как меняли ON-line и добавляли HAVING, чтобы добиться цели:

ON (s.`set_id` = p.`set_id` AND s.`set_dateadded` < p.`pic_dateadded`)
HAVING COUNT(*) < 3

Я пробовал всевозможные варианты этогос HAVING, но это не приближает меня.На самом деле он возвращает либо ноль результатов, либо одну строку на каждый набор, как только я добавлю в него какую-либо строку HAVING.Возможно, я пытаюсь использовать неправильное решение "наибольшие числа групп"?Может быть, потому что я хочу отсортировать по полю даты и времени, а не по идентификаторам с автоинкрементом?

Требуемые результаты

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

set_id | set_title | set_dateadded         | pic_id | pic_dateadded
4      | blah4     | 2011-10-04 00:00:00   | 32     | 2011-10-04 12:44:01
4      | blah4     | 2011-10-04 00:00:00   | 33     | 2011-10-04 12:44:02
3      | blah3     | 2011-10-03 00:00:00   | 26     | 2011-10-03 12:33:01
3      | blah3     | 2011-10-03 00:00:00   | 27     | 2011-10-03 12:33:02
2      | blah2     | 2011-10-02 00:00:00   | 11     | 2011-10-02 12:22:01
2      | blah2     | 2011-10-02 00:00:00   | 12     | 2011-10-02 12:22:02
1      | blah1     | 2011-10-01 00:00:00   | 1      | 2011-10-01 12:11:01
1      | blah1     | 2011-10-01 00:00:00   | 2      | 2011-10-01 12:11:02

Начинаю думать, что это может быть не самая плохая идея, если один запрос получит последние наборы, а затемиспользуйте цикл while в php с запросом, чтобы получить несколько картинок за комплект.: /


Решение

Рабочее решение найдено благодаря Джорджу Псаракису.Здесь показаны первые два изображения в последних четырех наборах:

SET @rownum=0;
SET @last_group_id=0;
SELECT gp.pic_id, gp.pic_dateadded, gs.*,
@rownum:=IF(gp.set_id<>@last_group_id,1,@rownum+1) AS rn, @last_group_id:=gp.set_id
FROM GalleryPics gp JOIN 
(
  SELECT * FROM GallerySets WHERE set_status='online'
  ORDER BY gs.set_dateadded DESC LIMIT 5
) AS gs
ON gs.set_id = gp.set_id 
HAVING rn < 4
ORDER BY gs.set_dateadded DESC, gp.pic_dateadded ASC

(время запроса составляет около 0,0030 с для 900+ наборов и 10000+ изображений)

1 Ответ

0 голосов
/ 02 ноября 2011

Я не очень уверен, но не могли бы вы попробовать следующее?

SET @rownum=0;
SET @last_group_id=0;
SELECT * FROM (
  SELECT gp.*,gs.*,@rownum:=IF(gp.set_id<>@last_group_id,1,@rownum+1) AS rn,
  @last_group_id:=gp.set_id FROM GalleryPics gp JOIN 
  (
    SELECT * FROM GallerySets WHERE set_status='online' 
    ORDER BY set_dateadded DESC LIMIT 4
  ) AS gs
  ON gs.set_id = gp.set_id 
  GROUP BY gp.set_id 
  ORDER BY gp.set_id,gp.pic_dateadded 
) tmp WHERE rn < 3
...