sql запрос: нет платежей за последние 90 дней

#mysql #sql

#mysql #sql

Вопрос:

Предположим, у меня есть клиент с большим количеством платежей. Как мне запросить, чтобы получить всех клиентов, у которых нет записей о платежах за последние 90 дней?

 clients
=======
id          integer
name        string

payments
========
id          integer
client_id   integer
created_at  datetime
  

По сути, обратное:

 select *
from clients
inner join payments on payments.client_id = clients.id
where payments.created_at > utc_timestamp() - interval 90 day
  

Надеюсь, более эффективный, чем:

 select *
from clients 
where id not in (
  select *
  from clients
  inner join payments on payments.client_id = clients.id
  where payments.created_at > utc_timestamp() - interval 90 day
)
  

Комментарии:

1. Последний запрос выполняется медленно или что-то в этомроде?

2. Какой диалект SQL вы используете?

3. @Oded: mysql; @Abe: еще не пробовал в производстве, но могу прибегнуть к нему, если понадобится

Ответ №1:

Убедитесь, что есть индекс на payments(client_id) , или даже лучше, payments(client_id, created_at ).

Для альтернативного способа написания вашего запроса вы могли бы попробовать not exists , например:

 select  *
from    clients c
where   not exists
        (
        select  *
        from    payments p
        where   p.payments.client_id = clients.id
                and payments.created_at > utc_timestamp() - interval 90 day
        )
  

Или эксклюзивное левое соединение:

 select  *
from    clients c
left join
        payments p
on      p.payments.client_id = clients.id
        and payments.created_at > utc_timestamp() - interval 90 day
where   p.client_id is null
  

Если оба работают медленно, добавьте explain extended выходные данные к вашему вопросу, чтобы мы могли понять, почему.

Комментарии:

1. Спасибо, эксклюзивное левое соединение, похоже, является правильным решением.

Ответ №2:

 select *
from clients
left join payments on 
    payments.client_id = clients.id and 
    payments.created_at > utc_timestamp() - interval 90 day
where payments.client_id is null