Как выбрать максимум 3 элемента для каждого пользователя в MySQL?

Я запускаю веб-сайт, на котором пользователи могут отправлять сообщения (например, фотографии). Элементы хранятся в базе данных MySQL.

Я хочу запросить последние десять размещенных элементов, но с ограничением не более 3 элементов может исходить от любого отдельного пользователя.

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

Спасибо заранее!

BR

Ответ 1

Это довольно легко с коррелированным подзапросом:

SELECT `img`.`id` , `img`.`userid`
FROM `img`
WHERE 3 > (
SELECT count( * )
FROM `img` AS `img1`
WHERE `img`.`userid` = `img1`.`userid`
AND `img`.`id` > `img1`.`id` )
ORDER BY `img`.`id` DESC
LIMIT 10 

Запрос предполагает, что более крупный id означает добавленный позже

Коррелированные подзапросы - это мощный инструмент!: -)

Ответ 2

Это сложно, потому что MySQL не поддерживает предложение LIMIT в подзапросах. Если бы это было так, это было бы довольно тривиально... Но, увы, вот мой наивный подход:

SELECT
  i.UserId,
  i.ImageId
FROM
  UserSuppliedImages i
WHERE
  /* second valid ImageId */
  ImageId = (
    SELECT MAX(ImageId)
    FROM UserSuppliedImages
    WHERE UserId = i.UserId
  )
  OR
  /* second valid ImageId */
  ImageId = (
    SELECT MAX(ImageId)
    FROM   UserSuppliedImages
    WHERE UserId = i.UserId
      AND ImageId < (
        SELECT MAX(ImageId)
        FROM UserSuppliedImages
        WHERE UserId = i.UserId
      )
    )
  /* you get the picture... 
     the more "per user" images you want, the more complex this will get */
LIMIT 10;

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

Для сравнения, на SQL Server это будет выглядеть так:

SELECT TOP 10
  img.ImageId,
  img.ImagePath,
  img.UserId
FROM
  UserSuppliedImages img
WHERE
  ImageId IN (
    SELECT TOP 3 ImageId
    FROM UserSuppliedImages 
    WHERE UserId = img.UserId
  )

Ответ 3

Сначала я должен выбрать 10 разных пользователей, а затем выбрать изображения у каждого из этих пользователей с помощью LIMIT 3, возможно, с помощью объединения всех этих и ограничить это до 10.

Это будет по крайней мере сужать данные, которые вам нужно обработать, до справедливой суммы.