2015-01-20 4 views
1

У меня есть база данных изображений, строки изображений обновляются последним IP-адресом, кто их просматривал, и обновляет столбец date_updated с текущей меткой времени. Я пытаюсь получить последние 5 изображений, но только каждый отдельный IP-адрес, я не хочу, чтобы один человек наполнил последний просмотренный результат.Выберите строки из базы данных, где значение в одном столбце отличается и ограничено 5 последними

Фидл:: http://sqlfiddle.com/#!2/d5b05/16

Желаемый результат: Желаемый результат при выборе из этого набора данных:

SELECT * FROM `image` ORDER BY `date_updated` DESC; 

| IMAGE | WIDTH | HEIGHT | DATE_ADDED | DATE_UPDATED | UPDATED_BY_IP | 
|---------|-------|--------|------------|--------------|---------------| 
| 1x1XGY4 | 1920 | 1080 | 1417546414 | 1421712314 | 192.168.0.7 | 
| 1x1XGY3 | 1920 | 1080 | 1417546413 | 1421712313 | 192.168.0.7 | 
| 1x1XGY2 | 1920 | 1080 | 1417546412 | 1421712312 | 192.168.0.10 | 
| 1x1XGY1 | 1920 | 1080 | 1417546411 | 1421712311 | 192.168.0.10 | 
| 1oApS54 | 1920 | 1080 | 1417138874 | 1421685474 | 192.168.0.2 | 
| 1oApS53 | 1920 | 1080 | 1417138873 | 1421685473 | 192.168.0.2 | 
| 1oApS52 | 1920 | 1080 | 1417138872 | 1421685472 | 192.168.0.10 | 
| 1oApS51 | 1920 | 1080 | 1417138871 | 1421685471 | 192.168.0.10 | 
| 1ydhtQ4 | 1920 | 1080 | 1421460434 | 1421685154 | 192.168.0.6 | 
| 1ydhtQ3 | 1920 | 1080 | 1421460433 | 1421685153 | 192.168.0.7 | 
| 1ydhtQ2 | 1920 | 1080 | 1421460432 | 1421685152 | 192.168.0.10 | 
| 1ydhtQ1 | 1920 | 1080 | 1421460431 | 1421685151 | 192.168.0.5 | 
| 1WyQib4 | 1920 | 1080 | 1420869354 | 1421634384 | 192.168.0.8 | 
| 1WyQib3 | 1920 | 1080 | 1420869353 | 1421634383 | 192.168.0.2 | 
| 1WyQib2 | 1920 | 1080 | 1420869352 | 1421634382 | 192.168.0.3 | 
| 1WyQib1 | 1920 | 1080 | 1420869351 | 1421634381 | 192.168.0.10 | 
| 1izDqg4 | 1920 | 1080 | 1416948144 | 1421608564 | 192.168.0.2 | 
| 1izDqg3 | 1920 | 1080 | 1416948143 | 1421608563 | 192.168.0.2 | 
| 1izDqg2 | 1920 | 1080 | 1416948142 | 1421608562 | 192.168.0.5 | 
| 1izDqg1 | 1920 | 1080 | 1416948141 | 1421608561 | 192.168.0.10 | 

С псевдо оператора выбора:

ВЫБОР * FROM image ГДЕ updated_by_ip отличные ORDER BY date_updated DESC LIMIT 5

| IMAGE | WIDTH | HEIGHT | DATE_ADDED | DATE_UPDATED | UPDATED_BY_IP | 
|---------|-------|--------|------------|--------------|---------------| 
| 1x1XGY4 | 1920 | 1080 | 1417546414 | 1421712314 | 192.168.0.7 | 
| 1x1XGY2 | 1920 | 1080 | 1417546412 | 1421712312 | 192.168.0.10 | 
| 1oApS54 | 1920 | 1080 | 1417138874 | 1421685474 | 192.168.0.2 | 
| 1ydhtQ4 | 1920 | 1080 | 1421460434 | 1421685154 | 192.168.0.6 | 
| 1ydhtQ1 | 1920 | 1080 | 1421460431 | 1421685151 | 192.168.0.5 | 

результат гардероба:

Лучшее, что я мог придумать это:

SELECT DISTINCT updated_by_ip, MAX(date_updated) AS date_updated 
FROM `image` GROUP BY updated_by_ip ORDER BY date_updated DESC LIMIT 5; 

Это дает мне :

| UPDATED_BY_IP | DATE_UPDATED | 
|---------------|--------------| 
| 192.168.0.7 | 1421712314 | 
| 192.168.0.10 | 1421712312 | 
| 192.168.0.2 | 1421685474 | 
| 192.168.0.6 | 1421685154 | 
| 192.168.0.5 | 1421685151 | 

из которых я мог бы сделать

while (SELECT DISTINCT updated_by_ip ...) 
{ 
    $result_rows[] = SELECT * FROM image 
        WHERE updated_by_ip = query[updated_by_ip] 
        AND date_updated = query[date_updated] LIMIT 1 
} 

Однако надеялся найти способ сделать это без того, чтобы сделать кучу пост-обработки и дополнительных запросов, а также, отбирая по updated_by_ip и date_updated Безразлично Кажется очень стабильным.

спасибо.

ответ

0

Чтобы сделать это без расширения MySQL GROUP BY, вы можете попробовать это:

Во-первых, получить самое последнее время обновления от пять различных IP-номеров, с этим подзапросом.

 SELECT updated_by_ip, MAX(date_updated) as date_updated 
     FROM image 
     GROUP BY updated_by_ip 
     ORDER BY 2 DESC 
     LIMIT 5 

Если таблица большая, индекс на (updated_by_ip, date_updated) поможет производительность.

Затем присоедините это к основному запросу к этому подзапросу, чтобы получить результат.

SELECT i.* 
    FROM image i 
    JOIN (
     SELECT updated_by_ip, MAX(date_updated) as date_updated 
      FROM image 
      GROUP BY updated_by_ip 
      ORDER BY 2 DESC 
      LIMIT 5 
     ) m USING(updated_by_ip, date_updated) 
ORDER BY i.date_updated DESC 

Смотреть это: http://sqlfiddle.com/#!2/d5b05/21/0

+0

Отлично работает, спасибо! – Snook

0

Это не самый красивый запрос (неправильно в соответствии со стандартом SQL), но он работает в MySQL:

SELECT * FROM `image` 
GROUP BY updated_by_ip 
ORDER BY `date_updated` DESC 

В Postgres вы бы использовать DISTINCT ON(...) но MySQL не поддерживает, что так просто группировка по столбцам вами хотят иметь четкое простейшее обходное решение. Альтернативой является использование подзапросов, но это работает немного менее оптимально.

+0

Спасибо за предложение, однако это не возвращает последнее изображение просматривалось для конкретного IP, группировка возвращает произвольную строку для каждого результата IP. – Snook

0

Один подход заключается в использовании переменных для перечисления строк:

SELECT i.* 
FROM (SELECT i.*, 
      (@rn := if(@uip = updated_by_ip, @rn + 1, 
         if(@uip := updated_by_ip, 1, 1) 
         ) 
      ) 
     FROM image i CROSS JOIN 
      (SELECT @uip := '', @rn := 0) vars 
     WHERE updated_by_ip 
     ORDER BY updated_by_ip, date_updated DESC 
    ) i 
WHERE seqnum <= 5;