Как получить 10 последних DISTINCT IP из таблицы MySQL? - PullRequest
4 голосов
/ 08 июня 2009

У меня есть таблица, содержащая данные pagehit (нормализованные), и мне нужно получить 10 последних уникальных ips.

Я пытался сделать это так:

SELECT * FROM spy_hits ORDER BY date desc GROUP BY ip LIMIT 10;

Что должно дать мне этот результат:

+-----+------------+-----+---------+----+------+------+---------+-------+-------+
| id  | date       | ip  | browser | os | page | host | referer | query | agent |
+-----+------------+-----+---------+----+------+------+---------+-------+-------+
| 354 | 1244442065 |   2 |       3 |  2 |   16 |    1 |      47 |    12 |     2 |
| 311 | 1244442000 |   1 |       2 |  1 |   16 |    1 |      36 |    12 |     1 |
+-----+------------+-----+---------+----+------+------+---------+-------+-------+
2 rows in set (0.00 sec)

Это последние уникальные посетители сайта.

Но вместо этого результата я получаю синтаксическую ошибку.

Так что я должен сделать этот запрос:

SELECT * FROM spy_hits GROUP BY ip ORDER BY date desc LIMIT 10;

Который, я думал, будет в порядке. Но это дает такой результат:

+-----+------------+-----+---------+----+------+------+---------+-------+-------+
| id  | date       | ip  | browser | os | page | host | referer | query | agent |
+-----+------------+-----+---------+----+------+------+---------+-------+-------+
| 280 | 1242130841 |   2 |       3 |  2 |   16 |    1 |      47 |    12 |     2 |
| 268 | 1242130818 |   1 |       2 |  1 |   16 |    1 |      36 |    12 |     1 |
+-----+------------+-----+---------+----+------+------+---------+-------+-------+
2 rows in set (0.00 sec)

Но это устанавливает порядок по дате после того, как он уже сгруппирован, поэтому он захватывает первые уникальные ips в таблице, которые также являются самыми старыми.

Итак, таблица идет так:

 id --- date
 268    1242130818    (Old)
  |      |
  V      V
 354    1244442065    (New)

Но я хочу, чтобы так было до того, как я сделаю группу:

 id --- date
 354    1244442065    (New)
  ^       ^
  |       |
 268    1242130818    (Old)

Я использую PHP вместе с ним, так что если у кого-то есть идеи, как получить результаты с помощью решения PHP.

Приветствия заранее:)

1 Ответ

3 голосов
/ 08 июня 2009

Если у вас есть несколько DISTINCT IP:

SELECT  ip, MAX(date) AS maxdate
FROM    (
        SELECT  ip, MAX(date) AS maxdate
        FROM    spy_hits
        GROUP BY
                ip
        )
ORDER BY
        maxdate DESC
LIMIT 10

Если у вас много DISTINCT IP:

SELECT  *
FROM    spy_hits so
WHERE   NOT EXISTS
        (
        SELECT  1
        FROM    spy_hits si
        WHERE   si.ip = so.ip
                AND si.date > so.date
        )
ORDER BY
        date DESC
LIMIT 10

Создание двух индексов для этой таблицы:

CREATE INDEX ix_spyhits_date ON spy_hits (date)
CREATE INDEX ix_spyhits_ip_date ON spy_hits (ip, date)

значительно улучшит эти запросы.

Смотрите эту запись в моем блоге для деталей производительности:

...