Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 寻找最长的连胜记录_Sql_Oracle_Oracle11gr2 - Fatal编程技术网

Sql 寻找最长的连胜记录

Sql 寻找最长的连胜记录,sql,oracle,oracle11gr2,Sql,Oracle,Oracle11gr2,我有以下格式的数据 match_id team_id won_ind ---------------------------- 37 Team1 N 67 Team1 Y 98 Team1 N 109 Team1 N 158 Team1 Y 162 Team1 Y 177 Team1 Y 188 Team1

我有以下格式的数据

match_id   team_id   won_ind
----------------------------
37          Team1    N
67          Team1    Y
98          Team1    N
109         Team1    N
158         Team1    Y
162         Team1    Y
177         Team1    Y
188         Team1    Y
198         Team1    N
207         Team1    Y
217         Team1    Y
10          Team2    N
13          Team2    N
24          Team2    N
39          Team2    Y
40          Team2    Y
51          Team2    Y
64          Team2    N
79          Team2    N
86          Team2    N
91          Team2    Y
101         Team2    N
这里的比赛ID是按时间顺序排列的,37是第一场比赛,217是第1队的最后一场比赛。获胜标志着该队是否赢得了比赛

因此,从上述数据来看,第一队输掉了第一场比赛,然后赢了一场比赛,然后输掉了两场比赛,然后连续赢了4场比赛,以此类推。现在我感兴趣的是为每支球队寻找最长的连胜记录

Team_id   longest_streak
------------------------
Team1     4
Team2     3
我知道如何在plsql中找到它,但我想知道是否可以在纯SQL中计算它。我试着使用LEAD、LAG和其他几个函数,但没有成功

我已经创建了提琴样本。

这应该可以工作, 在这里拉小提琴:


使用我发布的答案的变体


我在Teradata上也有类似的任务,将其修改为在Oracle上运行:

SELECT
   team_id,
   MAX(cnt)
FROM
 (
   SELECT
      team_id,
      COUNT(*) AS cnt
   FROM 
    (
      SELECT
        team_id, 
        match_id,
        won_ind,
        SUM(CASE WHEN won_ind <> 'Y' THEN 1 END) 
        OVER (PARTITION BY team_id 
              ORDER BY match_id 
              ROWS UNBOUNDED PRECEDING) AS dummy
      FROM matches
    ) dt
   WHERE won_ind = 'Y'
   GROUP BY team_id, dummy
 ) dt
GROUP BY team_id;

我没有时间复制writeup,但讨论了如何使用自连接和求和来实现这一点。只是一个问题,order by子句中的数字是什么意思?1=团队id,2=最长的序列,列select@Slartibartfast我认为在解码和求和函数中都需要按team_id进行分区。当我分别运行内部select语句时,new_group和group_noExcellent的计算存在一些差异。。虽然它与Slartibartfast的答案类似,但这很容易理解。为了与PostgreSQL和SQLite兼容,请将原始的_数据替换为查询:将原始的_数据match_id、team_id、won_id作为值37、'Team1','N',67、'Team1','Y'。。。美好的但是,如果最长条纹为1,则不会返回该值。将b.match\u id>a.match\u id更改为b.match\u id>=a.match\u id应该可以解决这个问题。结尾处还缺少右括号。很好。消除了对滞后函数的需要。
with original_data as (
  select 37  match_id, 'Team1' team_id, 'N' won_id from dual union all
  select 67  match_id, 'Team1' team_id, 'Y' won_id from dual union all
  select 98  match_id, 'Team1' team_id, 'N' won_id from dual union all
  select 109 match_id, 'Team1' team_id, 'N' won_id from dual union all
  select 158 match_id, 'Team1' team_id, 'Y' won_id from dual union all
  select 162 match_id, 'Team1' team_id, 'Y' won_id from dual union all
  select 177 match_id, 'Team1' team_id, 'Y' won_id from dual union all
  select 188 match_id, 'Team1' team_id, 'Y' won_id from dual union all
  select 198 match_id, 'Team1' team_id, 'N' won_id from dual union all
  select 207 match_id, 'Team1' team_id, 'Y' won_id from dual union all
  select 217 match_id, 'Team1' team_id, 'Y' won_id from dual union all
  select 10  match_id, 'Team2' team_id, 'N' won_id from dual union all
  select 13  match_id, 'Team2' team_id, 'N' won_id from dual union all
  select 24  match_id, 'Team2' team_id, 'N' won_id from dual union all
  select 39  match_id, 'Team2' team_id, 'Y' won_id from dual union all
  select 40  match_id, 'Team2' team_id, 'Y' won_id from dual union all
  select 51  match_id, 'Team2' team_id, 'Y' won_id from dual union all
  select 64  match_id, 'Team2' team_id, 'N' won_id from dual union all
  select 79  match_id, 'Team2' team_id, 'N' won_id from dual union all
  select 86  match_id, 'Team2' team_id, 'N' won_id from dual union all
  select 91  match_id, 'Team2' team_id, 'Y' won_id from dual union all
  select 101 match_id, 'Team2' team_id, 'N' won_id from dual 
),
----------------------------------------------------------------------
new_streaks as (
--
--  Identifying new streaks.
--  ------------------------
--
    select
      match_id,
      team_id,
      won_id,
--
--  A new streak is identfied if 
--
    case when
--
--    a) won_id = 'Y' and
--
      won_id = 'Y' and
--
--    b) the previous won_id = 'N':
--    
      lag(won_id) over (partition by team_id order by match_id) = 'N' 
--
--    
      then 1 
--
--    All other cases: no new streak:
      else 0 
-- 
     end new_streak
    from
      original_data
),
-------------------------------
streak_no as (
--
--  Assigning a unique number to each streak.
--  -----------------------------------------
--
select
--
    match_id,
    team_id,
--
--  In order to be able to count the number of records
--  of a streak, we first need to assign a unique number
--  to each streak:
--
    sum(new_streak) over (partition by team_id order by match_id) streak_no
--
from
    new_streaks 
where
--  We're only interested in «winning streaks»:
    won_id = 'Y'
),
-----------------------------------------------
--
--  Counting the elements per streak
--  --------------------------------
--
records_per_streak as (
select 
  count(*) counter,
  team_id,
  streak_no
from
  streak_no
group by
  team_id,
  streak_no
)
------------------------------------------------
--
--   Finally: we can find the «longest streak»
--   per team:
--
select
  max(counter) longest_streak,
  team_id
from
  records_per_streak 
group by team_id
;
select
    team_id,
    max(wins)
  from
    (
     select
            a.team_id,
            a.match_id amatch,
            b.match_id bmatch,
    (select count(distinct match_id) 
       from matches matches_inner
      where a.team_id = matches_inner.team_id
        and matches_inner.match_id between a.match_id and b.match_id) wins
      from
            matches a
            join matches b on a.team_id = b.team_id 
                      and b.match_id > a.match_id
     where
    not exists 
    (select 'x'
       from matches matches_inner
      where a.team_id = matches_inner.team_id
        and matches_inner.match_id between a.match_id and b.match_id
        and matches_inner.won_ind = 'N')

group by team_id
SELECT
   team_id,
   MAX(cnt)
FROM
 (
   SELECT
      team_id,
      COUNT(*) AS cnt
   FROM 
    (
      SELECT
        team_id, 
        match_id,
        won_ind,
        SUM(CASE WHEN won_ind <> 'Y' THEN 1 END) 
        OVER (PARTITION BY team_id 
              ORDER BY match_id 
              ROWS UNBOUNDED PRECEDING) AS dummy
      FROM matches
    ) dt
   WHERE won_ind = 'Y'
   GROUP BY team_id, dummy
 ) dt
GROUP BY team_id;