[英]Check if value was greater than x for y consecutive months period in changes history
我有成員級別更改的表。 它具有所有成員級別的歷史變化以及發生變化時的日期。 例如,我可以列出會員編號5的更改:
select * from memberlevelhistory where member = 5
結果:
member changedate level
5 2012-04-01 2
5 2012-03-01 3
5 2012-02-01 2
5 2011-02-01 6
5 2011-02-01 6
5 2010-03-15 6
5 2010-02-01 5
5 2010-01-01 5
5 2009-10-01 4
5 2009-08-27 2
5 2009-08-01 1
歷史表中的最后一個條目是當前級別。
問題:如何列出3個月或更長時間內水平高於或等於3的所有成員?
這是問題的簡化版本。 為了讓它變得更有趣,我只需要在這3個月期間內沒有低於起始水平的成員。 因此,如果一個成員在4個月期間開始了4級並且在上個月只是3級,那么該成員將被排除在列表之外。
任何幫助,即使是簡化的問題,我們都非常感謝。
擴大的視野:
我還需要在最近6個月的窗口內發生> = 3個月的水平> = 3的時期。
這可能是not exists
的情況。 如果在接下來的三個月內沒有其他條目的級別低於當前選定的記錄,則條目有效。 這解決了這兩個要求。 每個成員的最后一個條目可能存在問題,其中級別適當,但跨度未知。 我已決定刪除這些記錄,但您可能還有其他想法。
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
)
編輯:
我已經重寫了不存在()到左連接並添加了“持續到今天的最后一個條目”標准。
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
我認為100和101應該被包括在內,因為它們都有3個月的良好運行,並且這是在3月之前的六個月之前。
我所做的是在有人跑得好的時候生成范圍,然后在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
SELECT * FROM (
SELECT MEMBER, CHANGEDATE, LEVEL, COUNT(LEVEL) AS COUNT
FROM MEMBERLEVELHISTORY
GROUP BY MEMBER, CHANGEDATE, LEVEL)
WHERE LEVEL >= 3
AND COUNT >= 3;
這應該對我們的簡化版本有幫助,但為了連續分組結果超出我的意義!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.