반응형
가장 긴 연속 우승 기록 찾기
저는 다음과 같은 형식의 데이터를 가지고 있습니다.
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
여기서match_id
s는 연대순으로 37이 처음이고 217이 1팀이 하는 마지막 경기입니다. won_ind
그 팀이 경기에서 이겼는지 아닌지를 나타냅니다.
그래서 위의 자료로부터 1팀은 첫 경기에서 졌고, 그 다음에 한 경기에서 이겼고, 그 다음에 두 경기에서 졌고, 그 다음에 네 경기 연속으로 이겼습니다.이제 각 팀의 최장 연승 행진에 관심이 있습니다.
Team_id longest_streak
------------------------
Team1 4
Team2 3
나는 이것을 plsql에서 찾는 방법을 알고 있지만, 이것이 순수한 SQL에서 계산될 수 있는지 궁금합니다.저는 LED, LAG 등 여러 가지 기능을 사용해 보았지만 아무 효과가 없었습니다.
여기에 샘플 피들을 만들었습니다.
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
;
이것은 효과가 있을 것입니다, Fiddle 여기 있습니다: http://sqlfiddle.com/ #!4/31f95/27
SELECT team_id, MAX(seq_length) AS longest_sequence
FROM (SELECT team_id, COUNT(*) AS seq_length
FROM (SELECT team_id, won_ind,match_id, SUM(new_group) OVER(ORDER BY match_id) AS group_no
FROM (SELECT team_id, won_ind, match_id,
DECODE(LAG(won_ind) OVER(ORDER BY match_id), won_ind, 0, 1) AS new_group
FROM matches
ORDER BY team_id))
WHERE won_ind = 'Y'
GROUP BY team_id, group_no)
GROUP BY team_id
ORDER BY 2 DESC, 1;
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;
여기에 게시한 답변의 변형 사용
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
언급URL : https://stackoverflow.com/questions/17839015/finding-the-longest-streak-of-wins
반응형
'programing' 카테고리의 다른 글
Firebase(Phone Auth) iOS 오류 가져오기: 사용자 지정 URL 체계 등록 (0) | 2023.06.25 |
---|---|
PL/SQL ORA-06550의 "로컬 수집 유형이 허용되지 않음" 오류 (0) | 2023.06.20 |
Erno 32 파이프가 부러지는 것을 어떻게 예방합니까? (0) | 2023.06.20 |
텐서 흐름을 가져올 때 다음 오류가 발생합니다. 'numpy.core._multiarray_umath'라는 모듈이 없습니다. (0) | 2023.06.20 |
포인터가 자신을 가리킬 수 있습니까? (0) | 2023.06.20 |