Как создать запрос SQL, который отбрасывает повторяющиеся данные? - PullRequest
0 голосов
/ 03 июня 2019

У меня есть простая однотабличная база данных SQLite3, в которой хранится состояние доступности интернета с точки зрения моей локальной сети.

CREATE TABLE inet_visibility (
    recid  INTEGER PRIMARY KEY,
    type   INTEGER CHECK (type >= 0 AND type <= 2),   -- 0 = state change; 1 = periodic; 2 = other
    ts_new TEXT UNIQUE NOT NULL,                      -- entry created; UTC ISO8601
    ts_upd TEXT UNIQUE NOT NULL,                      -- entry updated; UTC ISO8601
    updcnt INTEGER NOT NULL,                          -- update tally
    state  INTEGER CHECK (state >= 0 AND state <= 2), -- 0 == unreachable; 1 = reachable; 2 = unknown
    byhost TEXT NOT NULL,                             -- IP of tester
    method TEXT NOT NULL,                             -- tool/process used to determine state
    note   TEXT DEFAULT ''                            -- optional note/comment
);

После нескольких дней работы я накопил следующие данные:

recid       type        ts_new               ts_upd               updcnt      state       byhost        method      note
----------  ----------  -------------------  -------------------  ----------  ----------  ------------  ----------  ----------
1           0           2019-05-20 10:31:48  2019-05-22 14:45:10  3106        1           192.168.1.47  heartbeat
2           0           2019-05-22 14:46:11  2019-05-23 07:41:52  981         0           192.168.1.47  ping
3           0           2019-05-23 07:42:52  2019-05-26 10:11:14  4438        1           192.168.1.47  heartbeat
4           0           2019-05-26 10:12:15  2019-05-26 10:12:15  0           1           192.168.1.47  ping
5           0           2019-05-26 10:13:24  2019-05-27 09:58:36  1415        1           192.168.1.47  heartbeat
6           0           2019-05-27 09:59:37  2019-05-27 09:59:37  0           1           192.168.1.47  ping
7           0           2019-05-27 10:00:49  2019-05-30 09:48:29  4277        1           192.168.1.47  heartbeat
8           0           2019-05-30 09:49:29  2019-05-30 09:49:29  0           1           192.168.1.47  ping
9           0           2019-05-30 09:50:34  2019-06-02 19:42:50  4877        1           192.168.1.47  heartbeat
10          0           2019-06-02 19:44:33  2019-06-02 19:44:33  0           0                         ping
11          0           2019-06-02 19:46:00  2019-06-03 10:32:44  881         1           192.168.1.47  heartbeat

Для основного отчета меня интересует только изменение state в самое ближайшее время. Поэтому для этого отчета мне нужны следующие данные:

recid       type        ts_new               ts_upd               updcnt      state       byhost        method      note
----------  ----------  -------------------  -------------------  ----------  ----------  ------------  ----------  ----------
1           0           2019-05-20 10:31:48  2019-05-22 14:45:10  3106        1           192.168.1.47  heartbeat
2           0           2019-05-22 14:46:11  2019-05-23 07:41:52  981         0           192.168.1.47  ping
3           0           2019-05-23 07:42:52  2019-05-26 10:11:14  4438        1           192.168.1.47  heartbeat
10          0           2019-06-02 19:44:33  2019-06-02 19:44:33  0           0                         ping
11          0           2019-06-02 19:46:00  2019-06-03 10:32:44  881         1           192.168.1.47  heartbeat

Два ключевых требования, которые следует отметить из приведенного выше четырехстрочного фрагмента, таковы: а) каждое значение state чередуется; и б) возвращается рек. 3 (самая ранняя), а не рек. с 4 по 9

Я понятия не имею, как написать запрос, чтобы получить эти результаты. sqlite3 history.db 'select * from inet_visibility group by state order by ts_upd asc' ... дает мне только записи 1 и 2. sqlite3 history.db 'select * from inet_visibility group by date(ts_upd),state order by ts_upd asc' ... немного ближе, но слишком много данных: я вижу записи 5, 7 и 9. Я знаю, что оба эти запроса неверны; Я пытался найти решение и столкнулся со стеной (в моих навыках SQL).

По сути ... Если вы рассматриваете данные как список заказов по возрастанию ts_upd, я хочу только те записи, в которых state изменяется относительно предыдущей записи.

В сторону: для этого основного отчета меня интересуют только recid, ts_upd и state - остальные столбцы можно игнорировать, если это имеет значение.

Может кто-нибудь предложить предложение или решение?

1 Ответ

1 голос
/ 03 июня 2019

В более поздних версиях SQLite вы можете использовать lag():

select iv.*
from (select iv.*,
             lag(state) over (partition by byhost order by recid) as prev_state
      from inet_visibility iv
     ) iv
where prev_state is null or prev_state <> state;

Предполагается, что «предыдущая строка» идентифицируется на основе recid. Это также предполагает, что вам нужно только сравнить byhost, чтобы увидеть, изменилось ли state.

EDIT:

Если вы хотите recid 11, тогда вас не волнует byhost. Удалить его из partition by:

select iv.*
from (select iv.*,
             lag(state) over (order by recid) as prev_state
      from inet_visibility iv
     ) iv
where prev_state is null or prev_state <> state;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...