Рефакторинг MySQL с GROUP BY и HAVING - PullRequest
0 голосов
/ 17 августа 2010

Я выполняю некоторую работу по рефакторингу кода PHP / MySQL и наткнулся на интересную проблему, и на данный момент я не могу найти правильное решение для нее.

У меня есть эта таблица:

CREATE TABLE example
(
    id        INT UNSIGNED  NOT NULL AUTO_INCREMENT PRIMARY KEY,
    userID    INT UNSIGNED  NOT NULL,
    timestamp INT UNSIGNED  NOT NULL,
    value     DECIMAL(10,2) NOT NULL
);

Я пытаюсь получить последнюю запись строки для каждого отдельного идентификатора пользователя.

В настоящее время это делается так:

SELECT DISTINCT userID
FROM example

, затем с помощьюPHP Я зацикливаюсь на результате и запускаю этот запрос для каждого отдельного идентификатора пользователя

SELECT *
FROM example
WHERE userID = %u
ORDER BY timestamp DESC
LIMIT 1

Я пытался объединить эти запросы в один, используя:

GROUP BY userID
HAVING MAX(timestamp)

, но безрезультатно.

Есть предложения?

Ответы [ 2 ]

3 голосов
/ 17 августа 2010
SELECT  e.*
FROM    (
        SELECT  DISTINCT userid
        FROM    example
        ) eo
JOIN    example e
ON      e.id =
        (
        SELECT  id
        FROM    example ei
        WHERE   ei.userid = eo.userid
        ORDER BY
                userid DESC, `timestamp` DESC, id DESC
        LIMIT 1
        )

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

Создайте индекс для (userid, timestamp, id), чтобы он работал быстро.

2 голосов
/ 17 августа 2010
SELECT e.id, e.userId, e.timestamp, e.value
FROM example e
WHERE NOT EXISTS
    (SELECT * FROM example e2 
     WHERE e.UserId = e2.UserId and e2.timestamp > e.timestamp)

или

SELECT e.id, e.userId, e.timestamp, e.value
FROM example e
JOIN (
    SELECT userId, MAX(timestamp) AS timestamp
    FROM example 
    GROUP BY userId
) x on 
     e.userId = x.userId and e.timestamp = x.timestamp
...