mysql присоединиться к таблице и найти самую последнюю запись в предложении where - PullRequest
0 голосов
/ 17 апреля 2020

У меня есть две таблицы

  • пользователей: id, электронная почта, firstName, lastName
  • подписки: id, userId, currentPeriodStart, currentPeriodEnd

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

select 
u.id 
from users u 
join subscriptions s on u.id s.userId 
where s.currentPeriodEnd > 1565827199 
ORDER BY u.lastName ASC

У пользователя может быть несколько подписок в таблице подписок. Мне нужно изменить приведенный выше запрос, чтобы он сравнивал последнюю подписку этого пользователя, а не первую найденную.

select * from subscriptions ORDER BY currentPeriodEnd DESC LIMIT 1

Я пробовал несколько разных вещей (таблица псевдонимов, sub запрос) Я нашел в другом месте на стеке потока без какой-либо удачи.

Ответы [ 2 ]

1 голос
/ 17 апреля 2020

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

select u.id 
from users u 
join (
    select userid
    FROM subscriptions
    GROUP BY userid
    HAVING MAX(currentPeriodEnd) > 1565827199 
) s ON s.userid = u.id
ORDER BY u.lastName ASC
1 голос
/ 17 апреля 2020

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

select u.*, s.*
from users u 
inner join subscriptions s on u.id = s.userId 
where s.currentPeriodEnd = (
    select max(s1.currentPeriodEnd) 
    from subscriptions s1 
    where s1.userId = u.id and s1.currentPeriodEnd > 1565827199
)
order by u.lastName

Для производительности рассмотрите индекс для subscriptions(userId, currentPeriodEnd).

В качестве альтернативы, если вы работаете MySQL 8.0 , вы можете использовать row_number():

select *
from (
    select 
        u.*, 
        s.*, 
        row_number() over(partition by u.id order by s.currentPeriodEnd desc)
    from users u 
    inner join subscriptions s on u.id = s.userId 
    where s.currentPeriodEnd > 1565827199
) t
where rn = 1
order by lastName
...