基于连续条件的 SQL 查询计数

Posted

技术标签:

【中文标题】基于连续条件的 SQL 查询计数【英文标题】:SQL query counting based on successive condition 【发布时间】:2013-08-15 17:58:08 【问题描述】:

我有一个看起来像这样的表:

+--------+-------+--------+ |测试名称|测试运行|结果| +--------+-------+--------+ |测试1 | 1 |失败 | +--------+-------+--------+ |测试1 | 2 |失败 | +--------+-------+--------+ |测试2 | 1 |失败 | +--------+-------+--------+ |测试2 | 2 |通行证 | +--------+-------+--------+ |测试3 | 1 |通行证 | +--------+-------+--------+ |测试3 | 2 |失败 | +--------+-------+--------+

该表用于存储测试结果的简要摘要。我想编写一个查询(使用 T-SQL,但任何方言都可以),返回每个测试失败的构建次数。使用示例作为输入,它应该返回如下结果集:

+--------+----------+ |测试名称|回归| +--------+----------+ |测试1 | 2 | +--------+----------+ |测试2 | 0 | +--------+----------+ |测试3 | 1 | +--------+----------+

请注意,查询应该只计算当前的'fail streak',而不是计算失败的总数。可以假设 MAX(TestRun) 是最近一次运行。

有什么想法吗?

编辑:语法

【问题讨论】:

你可以把WHERE放在GROUP BY之前。 请问什么版本的SQL Server 我使用的版本是2008-r2 【参考方案1】:

有点难看,但可以。

create table dbo.tests
(
    TestName nvarchar(10) not null
    , TestRun int not null
    , OutCome nvarchar(10) not null
)

insert into dbo.tests
select 'Test1', 1, 'Fail'
union all 
select 'Test1', 3, 'Fail'
union all 
select 'Test2', 1, 'Fail'
union all 
select 'Test2', 3, 'Pass'
union all 
select 'Test3', 1, 'Pass'
union all 
select 'Test3', 3, 'Fail'

; with c (TestName, TestRun, OutCome, TestId)
as
(
    select TestName, TestRun, OutCome
            , dense_rank() over (order by TestRun) as TestId
    from dbo.tests
) 

select t.TestName, max(t.TestId) - mt.MaxPassedTestRun as FailedRuns
from c t
        inner join
            (
                select TestName, sum(TestId) as MaxPassedTestRun
                from
                    (
                        select TestName, TestId 
                        from c
                        where OutCome = 'Pass'

                        union all 

                        select TestName, 0 as TestRun
                        from c
                        where OutCome = 'Fail'
                    ) mt
                group by mt.TestName
            ) mt on t.TestName = mt.TestName
group by t.TestName, MaxPassedTestRun, mt.MaxPassedTestRun

【讨论】:

如果TestRun 的数量不会增加一,这里只有一个问题(我的答案相同)。例如TestRun=1 和下一个TestRun = 4 已根据该要求进行了更新。仍然要求 id 不断增加,但不一定是连续的。【参考方案2】:
select a.TestName,a.TestRun,a.Outcome From table1 a join 
Table1 b on a.TestName=b.testname          
and a.Outcome='Fail' 
and a.TestRun>b.TestRun

【讨论】:

嗨 Sonam:感谢您的快速回复。不过,您的查询似乎正在计算所有失败。查询应该只计算当前的'fail streak',如示例(Test2) 我已经编辑了我的查询,如果这与您正在寻找的内容接近,请告诉我,或者请详细说明。【参考方案3】:

这是使用 CTE 的另一种方法:

;WITH streaks AS (
    SELECT t.Name, t.Run, t.Outcome 
    FROM TestRuns t
    INNER JOIN (SELECT Name, MAX(Run) AS MaxRun FROM TestRuns GROUP BY Name) maxes
    ON maxes.Name = t.Name AND maxes.MaxRun = t.Run

    UNION ALL

    SELECT t.Name, t.Run, t.Outcome
    FROM TestRuns t
    INNER JOIN streaks s ON s.Name = t.Name AND s.Outcome = 0
    WHERE t.Run = s.Run - 1 AND t.Outcome = 0
)

SELECT Name
, SUM(CASE WHEN Outcome = 0 THEN 1 ELSE 0 END) AS Regression
FROM streaks
GROUP BY Name

这里是SQL Fiddle 的数据样本

【讨论】:

有趣的方法......虽然我仍然无法理解它(条纹在其定义内与其自身相连)。我的测试表明它是正确的。谢谢。 p.s. SQL Fiddle 看起来也很有用 这是使用带有 CTE(公用表表达式)的递归查询,检查这个 Recursive Queries Using Common Table Expressions

以上是关于基于连续条件的 SQL 查询计数的主要内容,如果未能解决你的问题,请参考以下文章

Sql获取连续日期的计数

面试题: Hive-SQL查询连续活跃登录用户思路详解

面试题: Hive-SQL查询连续活跃登录用户思路详解

面试题: Hive-SQL查询连续活跃登录用户思路详解

Partition By In SQL 中的条件语句

SQL连续计数天数