Это можно сделать, но было бы намного эффективнее, если бы вы сохранили дату окончания каждого журнала. С вашей моделью вы должны сделать что-то вроде:
select l1.userid
from status_log l1
where l1.status='s'
and l1.logcreated = (select max(l2.logcreated)
from status_log l2
where l2.userid = l1.userid
and l2.logcreated <= date '2008-02-15'
);
С дополнительной колонкой это будет больше похоже на:
select userid
from status_log
where status='s'
and logcreated <= date '2008-02-15'
and logsuperseded >= date '2008-02-15';
(Извиняюсь за любые синтаксические ошибки, я не знаю Postgresql.)
Чтобы решить некоторые дополнительные вопросы, поднятые Филом:
Пользователь может быть снова перемещен из активного, приостановленного, отмененного в активное. Это упрощенная версия, в действительности, существует еще больше состояний, и людей можно перемещать непосредственно из одного состояния в другое.
Это будет выглядеть в таблице следующим образом:
userid from to status
FRED 2008-01-01 2008-01-31 s
FRED 2008-02-01 2008-02-07 c
FRED 2008-02-08 a
Я использовал ноль для даты "до" текущей записи. Я мог бы использовать будущую дату, например 2999-12-31, но в некоторых случаях предпочтительнее нуль.
Кроме того, для текущего статуса также не будет «даты окончания», так что я думаю, что это немного нарушает ваш запрос?
Да, мой запрос должен быть переписан как
select userid
from status_log
where status='s'
and logcreated <= date '2008-02-15'
and (logsuperseded is null or logsuperseded >= date '2008-02-15');
Недостатком этого дизайна является то, что всякий раз, когда изменяется статус пользователя, вы должны заканчивать дату его текущего status_log, а также создавать новый. Однако это не сложно, и я думаю, что преимущество запроса, вероятно, перевешивает это.