查询具有某些特征的连续行

时间:2009-05-14 10:20:51

标签: sql mysql

我有一张包含以下列的表格:

id int(10)
user int(10)
winner int(10)
profit double
created datetime

获胜者列可以是0或1.我想创建一个查询,返回按创建的日期时间列排序的最大连续获胜者数,以及第一个和最后一个创建日期以及连续获奖者那段时间的利润列。

2 个答案:

答案 0 :(得分:0)

我还没有测试过,但也许这会有效。

    select first_winner.created, last_winner.created, sum(mid_winner.profit)
          from T first_winner
     join T last_winner
          on first_winner.created <= last_winner.created
          and first_winner.winner = 1
          and last_winner.winner = 1
          and not exists -- no losers in between first_winner and last_winner
          (
           select * from T loser
           where loser.winner = 0
            and first_winner.created <= loser.created 
                                    and loser.created <= last_winner.created
          )
     join T mid_winner
          on first_winner.created <= mid_winner.created
                                 and mid_winner.created <= last_winner.created
          and mid_winner.winner = 1
     left join T bef_first_winner  -- winner before first winner with no losers in between
          on bef_first_winner.winner = 1
          and bef_first_winner.created < first_winner.created
          and not exists
          ( 
           select * from T b_loser
           where b_loser.winner = 0
            and bef_first_winner.created <= b_loser.created 
               and b_loser.created <= first_winner.created
          )
     left join T after_last_winner -- winner after last winner with no losers in between
          on after_last_winner.winner = 1
          and last_winner.created < after_last_winner.created
          and not exists
          ( 
           select * from T a_loser
           where a_loser.winner = 0
            and last_winner.created <= a_loser.created 
               and a_loser.created <= after_last_winner.created
          )
    where bef_first_winner.id is null
        and after_last_winner.id is null
   group by first_winner.created, last_winner.created

答案 1 :(得分:0)

这是一个可能的解决方案,用于查看每个用户ID的获胜条件。

select head.userid, head.id, sum(profit), count(*)
from #bingo b
inner join (
    select cur.userid, cur.id
    from #bingo cur
    left join #bingo prev 
        on cur.userid = prev.userid
        and prev.id < cur.id
        and not exists(
            select * 
            from #bingo inbetween 
            where prev.userid = inbetween.userid 
            and prev.id < inbetween.id 
            and inbetween.id < cur.id)
    where cur.winner = 1
    and IsNull(prev.winner,0) = 0
) head
    on head.userid = b.userid 
    and head.id <= b.id 


left join (
    select cur.userid, cur.id
    from #bingo cur
    left join #bingo prev 
        on cur.userid = prev.userid
        and prev.id < cur.id
        and not exists(
            select * 
            from #bingo inbetween 
            where prev.userid = inbetween.userid 
            and prev.id < inbetween.id 
            and inbetween.id < cur.id)
    where cur.winner = 1
    and IsNull(prev.winner,0) = 0
) nexthead 
    on nexthead.userid = b.userid 
    and head.id < nexthead.id 
    and nexthead.id <= b.id
where nexthead.id is null 
and b.winner = 1
group by head.userid, head.id

两个“头”子查询是相同的,您可以将它们放在视图中或支持它们的WITH中。 “头”子查询搜索连胜的每一个头;也就是说,第一场胜利或胜利之前就是亏损。我假设你的id随着时间的推移而增加,所以我没有使用Created专栏。

下面的查询搜索每一行的相应头部。 head的id必须小于或等于当前行的id,并且之间不能有其他头。

在那之后,只需要对头部进行分组,并将利润相加并计算行数。