Выбор лучшего результата из SQL - PullRequest
1 голос
/ 19 октября 2011

Я думаю, что это простая проблема, но я не могу ее решить.

Я хочу выбрать самый новый результат из таблицы и объединить его с одним элементом в другой таблице.

Проще говоря, вот простая схема:

Table 1 - Person
personId -PK - INT - AUTO ID
name - VARCHAR

Table 2 - Event
eventId - PK - INT - AUTO ID
personId - FK
timestamp  - DATETIME
event - ENUM ('Went Out', 'Came back')

Что я хотел бы сделать, это вернуть список всех людей и последние действия, совершенные каждым человеком

Пример результата:

name |personId |метка времени |eventId |событие

боб |1 |2011-08-7 3 |'ушел'

Я сделал простой запрос, соединив две таблицы, а затем выполнил группировку по personId и упорядочил по отметке времени, но возвращаемый результат всегда был первым действием для человека, а непоследний.

Есть идеи?

Ответы [ 5 ]

3 голосов
/ 19 октября 2011
SELECT p.name, p.personId, e.timestamp, e.eventId, e.event
FROM person p
  INNER JOIN Event e 
    ON e.eventId = 
      ( SELECT MAX(eventId)
        FROM Event 
        WHERE personId = p.personId 
        GROUP BY personId 
        LIMIT 1 )

OR

SELECT p.Name, p.ID, me.timestamp, me.ID, me.event
FROM person p
INNER JOIN (
            SELECT id, timestamp, event
            FROM Event 
            WHERE personId = p.ID               
            ORDER BY timestamp DESC LIMIT 1
           ) me
ON p.ID = me.id

PS: извините, но не могу сейчас проверить оба запроса

3 голосов
/ 19 октября 2011
SELECT 
  t1.Name,
  t1.PersonId,
  t2.TimeStamp,
  t2.EventId,
  t2.Event
FROM Table1 t1
INNER JOIN Table2 t2 ON t2.PersonId = t1.PersonID
INNER JOIN (SELECT
              PersonId,
              MAX(TimeStamp) as LastEventDateTime
            FROM Table2 
            GROUP BY PersonID) LE 
  ON LE.PersonID = t2.PersonID 
    AND LE.LastEventDateTime = t2.TimeStamp
0 голосов
/ 19 октября 2011

Альтернативное решение, использующее закрытый ключ, предполагает, что order by Id даст те же результаты, что и order by timestamp

SELECT p.Name, p.ID, me.timestamp, me.ID, me.event
FROM person p
JOIN (
      SELECT personId, MAX(ID) id 
      FROM Event 
      WHERE personId = p.ID               
      GROUP BY personId
     ) me
ON p.ID = me.id

Order by timestamp более естественно и, вероятно, безопаснее, но это быстрее.

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

Стандартным способом ANSI будет:

select name, personid, timestamp, eventid, event
from person
join event on event.personid=person.personid
  and event.timestamp=(select max(timestamp) from event e2
                       where e2.personid=person.personid)

Я давно не пользовался MySQL, и у меня нет удобной установки, но вы можете получить то, что хотите:

select name, personid, timestamp, eventid, event
from person
join event on event.personid=person.personid
group by personid
order by personid, timestamp desc

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

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

вы хотите сделать

ORDER by `timestamp` DESC

(по убыванию), чтобы получить самое высокое значение метки времени вместо самого низкого

...