2010-09-20 3 views
2

В настоящее время я выполняю левое соединение на двух таблицах. Первая таблица имеет идентификатор и имя человека, вторая таблица имеет идентификатор, идентификатор человека из таблицы 1, а затем временную метку (полета).Возврат 1 результат с левой стороны

People        Flights 
id | name    id | person_id | time 
------------    --------------------------- 
1  Dave    1   1   1284762115 
2  Becky    2   1   1284787352 
          3   2   1284772629 
          4   2   1286432934 
          5   1   1283239480 

Когда я выполняю мой левый присоединиться, я получаю список людей и их время полета, но то, что я хотел бы просто список людей, с временем полета с самым высоким ID

Я использую

SELECT p.id, p.name max(f.time) 
    FROM People p 
LEFT JOIN Flights f ON p.id = f.person_id 
GROUP BY p.id, p.name 

Однако, это только дает мне пОСЛЕДНЕЕ время полета, а не в последний раз полета закачанный в систему (то есть, самая высокая ID).

1 Dave 1284787352 
2 Becky 1286432934 

Так повторить, я хотел бы видеть имя человека, наряду с полетного времени их последнего Загрузил (самый высокий ID) время полета.

1 Dave 1283239480 
2 Becky 1286432934 
+1

Может быть, я так устал, но вы не можете выбрать 'макс (f.id)' вместо 'макс (f.time)'? – Patrick

+1

Нет, к сожалению, это не работает. –

+0

Тогда я устал. :-) – Patrick

ответ

6

Использование:

SELECT p.id, 
     p.name, 
     f.time 
    FROM PEOPLE p 
    JOIN FLIGHTS f ON f.person_id = p.id 
    JOIN (SELECT f.person_id, 
       MAX(f.id) AS max_id 
      FROM FLIGHTS f 
     GROUP BY f.person_id) x ON x.person_id = f.person_id 
          AND x.max_id = f.id 

Если вы используете базу данных, которая поддерживает аналитику:

SELECT p.id, 
     p.name, 
     x.time 
    FROM PEOPLE p 
    JOIN (SELECT f.person_id, 
       f.time, 
       ROW_NUMBER() OVER(PARTITION BY f.person_id 
            ORDER BY f.id DESC) AS rk 
      FROM FLIGHTS f) x ON x.person_id = p.id 
          AND x.rk = 1 

Если вы хотите, чтобы люди, в том числе и без полетов:

SELECT p.id, 
      p.name, 
      f.time 
    FROM PEOPLE p 
LEFT JOIN FLIGHTS f ON f.person_id = p.id 
    JOIN (SELECT f.person_id, 
        MAX(f.id) AS max_id 
      FROM FLIGHTS f 
     GROUP BY f.person_id) x ON x.person_id = f.person_id 
           AND x.max_id = f.id 

... и аналитическая версия:

SELECT p.id, 
      p.name, 
      x.time 
    FROM PEOPLE p 
LEFT JOIN (SELECT f.person_id, 
        f.time, 
        ROW_NUMBER() OVER(PARTITION BY f.person_id 
             ORDER BY f.id DESC) AS rk 
      FROM FLIGHTS f) x ON x.person_id = p.id 
           AND x.rk = 1 
+0

Прямо на деньги! Спасибо, Пони, я даже не был близок с тем, что у меня было = ( –

+0

Это выкинет любого, у кого нет полета, используйте левое соединение, а не внутреннее по его первоначальному запросу – Tahbaza

+0

А, для моего особого использования - В этом случае вы говорите, что оба соединения соединяются с левым соединением? –

1

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

Редакцией:

SELECT p.id, p.name MAX(f.time) 
    FROM People p 
LEFT JOIN Flights f ON p.id = f.person_id 
WHERE f.id in(SELECT MAX(id) FROM flights GROUP BY person_id) 
+0

# 1052 - Столбец 'id' в IN/ALL/ANY подзапрос неоднозначен –

+0

извините, см. Править. –

Смежные вопросы