【问题标题】:SQL: Calculate number of days since last successSQL:计算自上次成功以来的天数
【发布时间】:2020-05-25 20:26:49
【问题描述】:

下表代表给定测试的结果。

同一测试的每个结果要么通过 (error_id=0) 要么失败 (error_id 0) 我需要帮助来编写一个查询,该查询返回自上次良好运行以来的运行次数 (error_id= 0) 和日期。

|日期 | test_id | error_id | ---------------------------------- | 2019-12-20 | 123 | 23 | 2019-12-19 | 123 | 23 | 2019-12-17 | 123 | 22 | 2019-12-18 | 123 | 0 | 2019-12-16 | 123 | 11 | 2019-12-15 | 123 | 11 | 2019-12-13 | 123 | 11 | 2019-12-12 | 123 | 0

所以这个例子的结果应该是:

| 2019-12-18 | 123 | 4

因为测试 123 在 2019 年 12 月 18 日通过,这发生在 4 次运行前。

我有一个查询来确定给定的运行是否错误,但我无法对其应用适当的窗口函数来获得想要的结果

选择 test_id, Date, error_id, (CASE WHEN error_id 0 THEN 1 ELSE 0 END) as is_error 从测试结果

【问题讨论】:

    标签: sql postgresql window-functions


    【解决方案1】:

    您可以生成一个行号,与查询本身的排序相反:

    SELECT test_date, test_id, error_code, 
           (row_number() OVER (ORDER BY test_date asc) - 1) as runs_since_last_pass
    FROM tests
    WHERE test_date >= (SELECT MAX(test_date) FROM tests WHERE error_code=0)
    ORDER BY test_date DESC
    LIMIT 1;
    

    请注意,如果 test_date 不是唯一的,这将遇到问题。最好使用时间戳(精确到毫秒)而不是日期。

    这是一个 DBFiddle:https://www.db-fiddle.com/f/8gSHVcXMztuRiFcL8zLeEx/0

    如果有多个 test_id,您需要在行号函数中添加一个 PARTITION BY 子句,子查询会变得更复杂一些。通过 JOIN 而不是子查询提出一种方法可能更有效,但在认知上会更复杂。

    【讨论】:

      【解决方案2】:

      我认为您只需要聚合和一些过滤:

      select id, count(*),
             max(date) over (filter where error_id = 0) as last_success_date
      from t
      where date > (select max(t2.date) from t t2 where t2.error_id = 0);
      group by id;
      

      【讨论】:

        【解决方案3】:

        您必须为查询中的每个 test_id 使用良好运行的最大日期。你可以试试这个查询:

        select tr2.Date_error, tr.test_id,  count(tr.error_id)  from 
        testresults tr inner join (select max(Date_error), test_id 
        from testresult where error_id=0 group by test_id) tr2 on 
        tr.test_id=tr2.test_id and tr.date_error >=tr2.date_error 
        group by test_id
        

        【讨论】:

          【解决方案4】:

          这应该可以解决问题:

          select count(*) from table t,
          (select max(date) date from table where error_id = 0) good
          where t.date >= good.date
          

          基本上,您正在计算日期 >= 上次成功日期的行。

          请注意:如果需要天数,则完全不同的查询:

          select now()::date - max(test_date) last_valid from tests
          where error_code = 0;
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-08-04
            • 2019-08-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多