TxnID RunningAmount MemberID
==================================
1 80000 20
2 90000 20
3 70000 20 //<==== Falls but previously never below 100k, hence ignore
4 90000 20
5 110000 20
6 60000 20 //<==== Falls below 100k, hence we want ID 8
7 80000 20
8 120000 20
9 85000 28
...
....
如何构造查询以使其按成员分组,获取形成“ V”形的第一个transactionID。即使是伪代码也很好,我也无法分享我的尝试,因为我对如何做到完全一无所知。
更新:
很抱歉,没有对条件的解释。我们寻找的基本金额为100k。 ID是随机的,肯定需要行号
我们忽略ID = 5
之前的所有交易,因为它们的runningAmount
从未超过100k。
现在,当ID=5
超过10万时,我们检查ID=5
之后的交易是否runningAmount
中的下降趋势低于10万。
我们立即看到ID=6
降至10万以下,因此我们希望找到再次超过10万(如果有)的第一笔交易。
从上面的数据样本中,预期结果仅为一条记录,即ID=8
。
对于每个成员,根据我提到的条件,只会找到一个或零个记录
答案 0 :(得分:1)
尝试此查询:
declare @tbl table(TxnID int, RunningAmount int, MemberID int);
insert into @tbl values
(1, 80000, 20),
(2, 90000, 20),
(3, 70000, 20),
(4, 90000, 20),
(5, 110000, 20),
(6, 60000, 20),
(7, 120000, 20),
(8, 85000, 28);
select TxnID, RunningAmount, MemberID,
LAG(VShape) over (partition by MemberID order by TxnID) VShape
from (
select TxnID, RunningAmount, MemberID,
case when rn < lagrn and rn < leadrn then 1 else 0 end VShape
from (
select *,
LAG(rn) over (partition by MemberID order by TxnID) lagRn,
LEAD(rn) over (partition by MemberID order by TxnID) leadRn
from (
select TxnID,
RunningAmount,
MemberID,
ROW_NUMBER() over (partition by MemberID order by RunningAmount) rn
from @tbl
) a
) a
) a
最后一列VShape
指示RunningAmount
中的值是否完成了V形(尽管您可以更清楚地了解其含义,而不是每个人都可以弄清楚)。现在,您可以根据RunningAmount
过滤值(但值低于或高于100k)。
以下是不具有LAG
和LEAD
函数的SQL Server早期版本的版本:
;with cte as (
select *,
ROW_NUMBER() over (partition by MemberID order by RunningAmount) rn
from @tbl
), cte2 as (
select c1.TxnID, c1.RunningAmount, c1.MemberID, c1.rn, c2.rn [lagRn] , c3.rn [leadRn]
from cte c1
left join cte c2 on c1.TxnID = c2.TxnID + 1 and c1.MemberID = c2.MemberID
left join cte c3 on c1.TxnID = c3.TxnID - 1 and c1.MemberID = c3.MemberID
), cte3 as (
select TxnID, RunningAmount, MemberID,
case when rn < lagrn and rn < leadrn then 1 else 0 end VShape
from cte2
), FinalResult as (
select c1.TxnID, c1.RunningAmount, c1.MemberID, c2.VShape
from cte3 c1
left join cte3 c2 on c1.TxnID = c2.TxnID + 1 and c1.MemberID = c2.MemberID
)
select fr.*, fr2.RunningAmount RunningAmountLagBy2 from FinalResult fr
left join FinalResult fr2 on fr.TxnID = fr2.TxnID + 2
where fr.RunningAmount > 100000 and fr2.RunningAmount > 100000 and fr.VShape = 1
更新
问题更新后,以下是解决方法:
select TxnID from (
select *, ROW_NUMBER() over (partition by VShape order by TxnID) CompletesVShape from (
select TxnID,
RunningAmount,
MemberID,
sum(case when RunningAmount >= 100000 then 1 else 0 end) over (partition by MemberID order by TxnID rows between unbounded preceding and current row) VShape
from @tbl
) a
) a where VShape > 1 and CompletesVShape = 1
答案 1 :(得分:0)
根据您的问题更新,并假设V形的必要条件是高于和低于运行量> 100000,而中间小于高于和低于运行量,以下是显示如何在2008 sql server中执行此操作的查询。
另请参见 live demo
; with firstlargeamount as
(
select MemberId, minTrxid=min(TxnID)
from t
where RunningAmount>100000
group by MemberId
)
,tbl as
(
select *,
rn=row_number() over( partition by MemberId order by TxnId)
from
t
)
select t3.*,f.*
from tbl t1
join tbl t2
on
t1.memberId=t2.memberid and t1.rn=t2.rn +1
and t1.RunningAmount<t2.RunningAmount
join tbl t3
on
t1.memberId=t3.memberid and t1.rn=t3.rn -1
and t1.RunningAmount<t3.RunningAmount
join firstlargeamount f
on
f.Memberid=t2.memberid and f.minTrxid>=t1.TxnID
说明:
第一步是在成员级别生成行号序列,如cte tbl和cte firstlargeamount中的最小限制交易
第二步是双重自连接,以找到满足V形标准的每行上下记录,并与firstlargemount结合以找到满足100000要求的行 请注意,上面和下面的记录只是使用在步骤1中计算的当前记录的行号中的+ 1 / -1来找到的