Как выбрать только самую последнюю запись на основе идентификатора пользователя, который может находиться в любом из двух столбцов? - PullRequest
3 голосов
/ 12 октября 2011

У меня есть таблица messages, которая структурирована примерно так:

from  |  to  |  date
-----------------------------------
1     |  3   |  2011-09-23 11:51:44
3     |  1   |  2011-09-23 11:56:29
3     |  2   |  2011-10-04 10:20:01
2     |  3   |  2011-10-05 07:48:00

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

часть, которая вводит меня в заблуждение, - то, что самое последнее сообщение может быть или отправлено или получено, что означает, что идентификационный номер пользователя может быть или в столбце from или to.Я не уверен, как тестировать оба столбца так, как мне нужно.

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

РЕШЕНИЕ Оказывается, это был не совсем простой случай.Видору потребовалось некоторое время, чтобы помочь мне с этим, и следующий запрос, наконец, справился с этой задачей.Он не был тщательно протестирован, но пока работает нормально:

SELECT m.*
FROM   messages m
       JOIN (SELECT Max(x.id)      AS `id`,
                    x.userid,
                    x.partnerid,
                    Max(x.mostrecent) AS `mostrecent`
             FROM  (SELECT Max(id)     `id`,
                           `from`         AS `userid`,
                           `to`           AS `partnerid`,
                           Max(`created`) AS `mostrecent`
                    FROM   messages
                    GROUP  BY `from`,
                              `to`
                    UNION
                    SELECT Max(id)     `id`,
                           `to`           AS `userid`,
                           `from`         AS `partnerid`,
                           Max(`created`) AS `mostrecent`
                    FROM   messages
                    GROUP  BY `to`,
                              `from`) AS `x`
             GROUP  BY x.`userid`,
                       x.`partnerid`) AS `y`
         ON y.id = m.id
WHERE  y.userid = $userid

Ответы [ 4 ]

1 голос
/ 12 октября 2011

RE-EDITED

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

Итак, рассмотрим случай, когда у вас теперь есть дополнительная запись в данных:

1    |     4    | 2011-10-04 08:34:12

Мой пересмотренный запрос выглядит следующим образом:

SELECT userid, partnerid, max(mostRecent) from (
    SELECT [from] as [userid], [to] as [partnerid], max([date]) as [mostrecent] FROM messages GROUP BY [from], [to]
    UNION 
    SELECT [to] as [userid], [from] as [partnerid],max([date]) as [mostrecent] FROM messages GROUP BY [to], [from]
) [x]
WHERE userid = ?
GROUP BY userid, partnerid

Итак, наш внутренний UNION дает нам набор данных, содержащий userid вместе с partnerid, то есть с кем они общаются. Это может быть создано отдельно как представление, если вы хотите, чтобы упростить запрос.

Внешний SELECT затем извлекает одну запись для каждого «партнера», с которым указанный userid имел чат, вместе с самой последней датой.

Функция Max() достигает самой последней даты, а GROUP BY обеспечивает, чтобы мы возвращали более одной записи для каждого партнера.

0 голосов
/ 12 октября 2011

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

CREATE VIEW dataview AS 
(SELECT t1.from AS userid, t1.date FROM messages AS t1) 
UNION
(SELECT t2.to AS userid, t2.date FROM messages AS t2)

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

0 голосов
/ 12 октября 2011

Похоже, вы хотите что-то вроде:

SELECT MAX(date), * FROM messages WHERE to IN (
    SELECT DISTINCT to FROM messages WHERE from = :id
) GROUP BY to
UNION
SELECT MAX(date), * FROM messages WHERE from IN (
    SELECT DISTINCT from FROM messages WHERE to = :id
) GROUP BY from
ORDER BY 1

Где id - это параметр, который вы используете для идентификатора пользователя.

0 голосов
/ 12 октября 2011

Я думаю, вы, вероятно, хотите что-то вроде этого:

SELECT MAX(date)
FROM messages
WHERE from = $userid
   OR to   = $userid

Вы бы заменили $userid на фактическое значение, будем надеяться, используя подготовленные заявления . : -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...