Sql 如何查询V形数据?

Sql 如何查询V形数据?,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,如何构造查询以使其按成员分组,获取形成V形的第一个transactionID。即使伪代码也可以,我不能分享我的尝试,因为我完全不知道如何去做 更新: 很抱歉没有解释这些条件。我们看的基数是10万。ID是随机的,我们一定要有行数 我们忽略ID=5之前的所有事务,因为它们的运行量从未超过100k 现在,当ID=5超过100k时,我们检查ID=5之后的交易是否有低于100k的运行金额下降趋势 我们立即看到ID=6降到100k以下,因此我们希望找到第一个超过100k的事务(如果有) 从上面的数据样本中,

如何构造查询以使其按成员分组,获取形成V形的第一个transactionID。即使伪代码也可以,我不能分享我的尝试,因为我完全不知道如何去做

更新:


很抱歉没有解释这些条件。我们看的基数是10万。ID是随机的,我们一定要有行数

我们忽略ID=5之前的所有事务,因为它们的运行量从未超过100k

现在,当ID=5超过100k时,我们检查ID=5之后的交易是否有低于100k的运行金额下降趋势

我们立即看到ID=6降到100k以下,因此我们希望找到第一个超过100k的事务(如果有)

从上面的数据样本中,预期结果只有一条记录,即ID=8

对于每个成员,根据我提到的条件,只能找到一条或零条记录

尝试以下查询:

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
...
....
更新

问题更新后,以下是解决方案:

;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

根据您的问题更新,并假设V形的必要条件是高于和低于运行量>100000,中间值小于高于和低于运行量,下面是一个查询,显示如何在2008 sql server中执行此操作

也看到

说明:

第一步是在成员级别生成一个行号序列,作为cte tbl和cte firstlargeamount中的最小限制事务

第二步是双自联接,以查找每行上下满足V形条件的记录,以及与firstlargeamount联接以查找满足100000条件的行
请注意,上面和下面的记录只是使用步骤1中计算的当前记录行号中的+1/-1来查找的

不清楚(至少我不清楚)您实际想要实现的目标。您能否提供发布的样本数据的预期结果?另外,您能否详细说明生成结果的逻辑?因此,您希望找到三条连续的记录,其运行量在100k以上、100k以下、100k以上,并且您希望最后一条记录的id?@giorgosbetos:从上述数据样本中,我只想要ID=7的记录,在sql server 2008上没有滞后或超前。@EzLo更新了答案:@MichałTurczyn:很抱歉前面没有解释。我已经编辑了我的问题,希望你能花点时间来确保我们有相同的理解。许多的thanks@Isaac我理解你的问题。我的问题解决了吗?如果没有,怎么了?如果是这样,你可以接受答案:@MichałTurczyn:非常接近。但是ID=4上的VShape不应该是1,因为ID=4之前的事务从来没有超过100kSorry,因为前面没有解释。我已经编辑了我的问题,希望你能花点时间来确保我们有相同的理解。非常感谢
;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
   ; 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