这可能是not exists
. 如果在接下来的三个月内没有其他条目的级别低于当前选择的记录,则该条目有效。这解决了这两个要求。在级别合适但跨度未知的情况下,每个成员的最后一个条目可能存在问题。我已决定删除这些记录,但您可能有其他想法。
带有示例的 Sql Fiddle 在这里。
select distinct mlh.member
from memberlevelhistory mlh
where mlh.level >= 3
and not exists
(
select null
from memberlevelhistory mlh2
where mlh2.member = mlh.member
and mlh2.changedate >= mlh.changedate
and mlh2.changedate < dateadd(month, 3, mlh.changedate)
and mlh2.level < mlh.level
)
-- The last entry might have appropriate level
-- But we cannot tell how long it lasted,
-- So we are going to remove it.
and exists
(
select null
from memberlevelhistory mlh3
where mlh3.member = mlh.member
and mlh3.changedate > mlh.changedate
)
编辑:
我已将 not exists() 重写为左连接并添加了“最后一个条目持续到今天”标准。
带有示例的 Sql Fiddle 在这里。
select distinct mlh.member
from memberlevelhistory mlh
left join memberlevelhistory mlh2
on mlh2.member = mlh.member
and mlh2.changedate >= mlh.changedate
and mlh2.changedate < dateadd(month, 3, mlh.changedate)
and mlh2.level < mlh.level
where mlh.level >= 3
and mlh2.member is null
and datediff(month, mlh.changedate, getdate()) >= 3
查询重写:
; with ranges as
(
select mlh.member, mlh.changedate StartRange, min(isnull(mlh2.changedate, getdate())) EndDate
from memberlevelhistory mlh
left join memberlevelhistory mlh2
on mlh2.member = mlh.member
and mlh2.changedate >= mlh.changedate
and mlh2.level < mlh.level
where mlh.level >= 3
group by mlh.member, mlh.changedate
having datediff (month, min(isnull(mlh2.changedate, getdate())), getdate()) <= 6
and datediff (month, mlh.changedate, min(isnull(mlh2.changedate, getdate()))) >= 3
)
select distinct member
from ranges
而 Sql Fiddle 就在这里。
我认为应该包括 100 和 101,因为两者都在 3 个月内运行良好,而这发生在 3 月,也就是在这一刻之前的 6 个月。
我所做的是在某人运行良好时生成范围,然后在 3 个月或更长时间的持续时间和过去六个月的结束日期测试此范围。
更新:如果我最终做对了,您需要在过去六个月中持续三个月。计算一个可能会将更改日期截断为当前日期 - 六个月。使用它作为起点,并找到一个范围的终点,首先mlh
以较低级别和较高日期作为终点,有足够的信息来计算持续时间。
; with ranges as
(
select mlh.member,
-- If good range starts more than six months before today
-- truncate it to today - 6 months
case when datediff (month, mlh.changedate, getdate()) > 6
then dateadd(month, -6, getdate())
else mlh.changedate
end StartRange,
-- First bad mlh after current changedate
min(isnull(mlh2.changedate, getdate())) EndRange
from memberlevelhistory mlh
left join memberlevelhistory mlh2
on mlh2.member = mlh.member
and mlh2.changedate >= mlh.changedate
and mlh2.level < mlh.level
where mlh.level >= 3
group by mlh.member, mlh.changedate
-- As above, limit good range to max six months before today
-- And only get those lasting at least three months
having datediff (month, case when datediff(month, mlh.changedate, getdate()) > 6
then dateadd(month, -6, getdate())
else mlh.changedate
end,
min(isnull(mlh2.changedate, getdate()))) >= 3
)
select distinct member
from ranges
带有示例的 Sql Fiddle 在这里。