我有一个带有buildID(UUID,而不是int)的简单表,Repository,日期和结果:
BuildID Repository BuildDateTime Result
------------------------------------------------------
1234 Repo1 2017-01-02T01:23:56 Fail
2224 Repo1 2017-01-02T01:22:56 Fail
3234 Repo1 2017-01-02T01:20:56 Success
4234 Repo2 2017-01-01T01:20:00 Fail
5234 Repo2 2017-01-01T01:19:00 Success
6234 Repo2 2017-01-01T01:18:00 Success
7234 Repo3 2017-01-01T01:17:30 Success
8234 Repo2 2017-01-01T01:17:00 Success
我想确定,对于每个构建,存储库的构建具有相同结果的行中连续构建的数量,以及它何时启动条纹。我想把它放到一个视图中,所以结果看起来像这样:
BuildID Repository BuildDateTime Result Streak StreakStartDateTime
-------------------------------------------------------------------------------
1234 Repo1 2017-01-02T01:23:56 Fail 2 2017-01-02T01:22:56
2224 Repo1 2017-01-02T01:22:56 Fail 1 2017-01-02T01:22:56
3234 Repo1 2017-01-02T01:20:56 Success 1 2017-01-02T01:20:56
4234 Repo2 2017-01-01T01:20:00 Fail 1 2017-01-01T01:20:00
5234 Repo2 2017-01-01T01:19:00 Success 3 2017-01-01T01:17:00
6234 Repo2 2017-01-01T01:18:00 Success 2 2017-01-01T01:17:00
7234 Repo3 2017-01-01T01:17:30 Success 1 2017-01-01T01:17:30
8234 Repo2 2017-01-01T01:17:00 Success 1 2017-01-01T01:17:00
我一直在使用滞后函数,这有助于我理解之前的X行。问题是我需要返回以查找结果的行数因行而异。我开始认为这是一个死胡同。
感谢任何帮助。
答案 0 :(得分:3)
可以使用lag
完成此操作。
select t.*
,row_number() over(partition by repository,grp order by buildDatetime) as streak
,min(buildDatetime) over(partition by repository,grp) as streakStartDatetime
from (select t.*
,sum(prev_same_or_not) over(partition by repository order by buildDatetime) as grp
from (select t.*
,case when lag(result) over(partition by repository order by buildDatetime) = result then 0 else 1 end as prev_same_or_not
from tbl t
) t
) t
看起来势不可挡,但这是如何运作的。
答案 1 :(得分:1)
这是另一种做法。基本上为每个构建在历史记录中分配一个订单,并在历史记录中查找最早的一个订单,它们具有相同的状态,并且两者之间没有任何状态。
WITH CTE_Builds AS (
SELECT *
, RN = ROW_NUMBER() OVER (PARTITION BY Repository ORDER BY BuildDateTime)
FROM BuildHistory
)
SELECT a.*
, Streak = ISNULL(a.RN - x.MIN_RN,0) + 1
, StreakStartDateTime = ISNULL(x.MIN_DATE, a.BuildDateTime)
FROM CTE_Builds a
OUTER APPLY (
SELECT MIN_RN = MIN(RN), MIN_DATE = MIN(BuildDateTime)
FROM CTE_Builds b
WHERE b.Repository = a.Repository
AND b.RN < a.RN
AND b.Result = a.Result
AND NOT EXISTS (
SELECT *
FROM CTE_Builds c
WHERE c.Repository = b.Repository
AND c.RN BETWEEN b.RN and a.RN
AND c.Result != b.Result
)
) x
ORDER BY a.Repository, a.BuildDateTime DESC