2015-10-12 2 views
0

У меня есть две таблицы:Выберите строки, где последняя строка соответствующей таблицы имеет определенное значение

User (id, name) 
UserEvent (id, user_id, name, date) 

Как я могу получить все пользователи, где последний (упорядоченные по дате) UserEvent.name имеет значение «играл «?

Я написал пример на SQLFiddle с некоторыми конкретными данными: http://sqlfiddle.com/#!9/b76e24 - Для этого сценария я бы просто получить «Mery» из таблицы User, потому что даже если «Джон» связал событие имя последнего не является «играл» ,

+0

Правильно ли, что идентификатор в UserEvent всегда равен 1, а не автоматически увеличивается? –

+0

Отредактировано, извините.Это автоинкремент. –

+0

Ваша скрипка для MySQL? Но вы все еще говорите о Postgres, верно? Имя таблицы 'User' невозможно без двойного цитирования. Типы данных также не имеют смысла для Postgres. Пожалуйста, предоставьте действительный, последовательный вопрос. И, как всегда, ваша версия Postgres, пожалуйста. –

ответ

0

Возврат максимальной даты из пользовательской группы событий по идентификатору пользователя. Возьмите этот набор результатов и присоедините его к пользовательскому событию по идентификатору пользователя и максимальной дате и фильтру только для воспроизведенных записей.

0

Здесь:

Сначала я получить MAX ID от каждого пользователя и присоединить его к ROW с этим идентификатором , чтобы проверить, если статус являются «играли», если да, то я получить имя пользователя их.

SELECT 
    ids.*, 
    u.name, 
    ue.* 
FROM (
    SELECt max(id) AS id from UserEvent 
    GROUP by user_id 
) as ids 
LEFT JOIN UserEvent ue ON ue.id = ids.id 
LEFT JOIN User u ON u.id = ue.user_id 
WHERE ue.name = 'played'; 
+0

Почему вы проголосуете? ?????? –

+0

Я проголосовал, потому что запрос не вернет желаемый результат, который вы должны были заметить, когда вы его протестировали. См. Http://sqlfiddle.com/#!9/b76e24/8 По крайней мере, не с образцом скрипта, представленным в вопросе. Возможно, это было правильно при других предположениях, хотя – jpw

+0

Я исправил ответ –

1

Это, вероятно, самый быстрый:

SELECT u.* 
FROM usr u -- avoiding "User" as table name 
JOIN LATERAL (
    SELECT name 
    FROM userevent 
    WHERE user_id = u.id 
    ORDER BY date DESC NULLS LAST 
    LIMIT 1 
    ) ue ON ue.name = 'played'; 

LATERAL требует Postgres 9.3+:

Или вы могли бы использовать DISTINCT ON (быстрее на несколько строк для каждого пользователя):

SELECT u.* 
FROM usr u -- avoiding "User" as table name 
JOIN (
    SELECT DISTINCT ON (user_id) 
      user_id, name 
    FROM userevent 
    ORDER BY user_id, date DESC NULLS LAST 
    ) ue ON ue.user_id = u.id 
     AND ue.name = 'played'; 

Детали для DISTINCT ON:

SQL Fiddle с действительным теста.

Если date определено NOT NULL, вам не нужно NULLS LAST. (. Ни в индексе ниже)

Ключ для чтения производительность для обоих, но особенно первый запрос является соответствие Multicolumn индекс:

CREATE INDEX userevent_foo_idx ON userevent (user_id, date DESC NULLS LAST, name); 

Рядом: Никогда не используйте reserved words в качестве идентификаторов.

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