SQL: подсчитать количество дней с момента последнего успеха - PullRequest
1 голос
/ 10 февраля 2020

Следующая таблица представляет результаты данного теста.

Каждый результат для одного и того же теста является либо успешным (error_id = 0), либо неудачным (error_id <> 0). Мне нужна помощь для написания запроса, который возвращает количество прогонов с момента последнего хорошего прогона (error_id = 0 ) и дату.

| Date       | 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 прошел PASS на 2019-12-18, и это произошло 4 запуска go.

У меня есть запрос, чтобы определить, является ли данный прогон ошибочным или нет, но у меня проблемы с применением соответствующей оконной функции для получения желаемого результата

select test_id, Date, error_id,  (CASE WHEN error_id  0 THEN 1 ELSE 0 END) as is_error
from testresults 

Ответы [ 4 ]

1 голос
/ 10 февраля 2020

Вы должны использовать Максимальную дату хороших прогонов для каждого 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
1 голос
/ 10 февраля 2020

Я думаю, вы просто хотите агрегацию и некоторую фильтрацию:

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;
1 голос
/ 10 февраля 2020

Вы можете сгенерировать номер строки в обратном порядке из сортировки самого запроса:

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 вместо подзапроса, но это было бы более сложным в познавательном отношении.

0 голосов
/ 10 февраля 2020

Это должно сработать:

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;
...