Выбор последних последовательных записей, соответствующих условию, с PostgreSQL - PullRequest
0 голосов
/ 16 мая 2018

Я ищу запрос PostgreSQL, чтобы найти последние последовательные записи, которые соответствуют условию. Позвольте мне объяснить это лучше на примере:

|  ID  |  HEATING STATE  |  DATE       |
| ---- | --------------- |  ---------- |
|  1   |  ON             |  2018-02-19 |
|  2   |  ON             |  2018-02-20 |
|  3   |  OFF            |  2018-02-20 |
|  4   |  OFF            |  2018-02-21 |
|  5   |  ON             |  2018-02-21 |
|  6   |  OFF            |  2018-02-21 |
|  7   |  ON             |  2018-02-22 |
|  8   |  ON             |  2018-02-22 |
|  9   |  ON             |  2018-02-22 |
| 10   |  ON             |  2018-02-23 |

Мне нужно найти все последние последовательные записи с датой> = 2018-02-20 и Heating_state ON, то есть с идентификаторами 7, 8, 9, 10. Моя главная проблема заключается в том, что они должны быть последовательный .

Для дальнейшего уточнения, если необходимо:

  • ID 1 исключен, поскольку старше 2018-02-20
  • ID 2 исключен, поскольку за ним следует ID 3, для которого состояние нагрева ВЫКЛ.
  • ID 3 исключен, поскольку он имеет состояние нагрева ВЫКЛ.
  • ID 4 исключен, потому что за ним следует ID 5, у которого выключен обогрев
  • ID 5 исключен, потому что он имеет состояние нагрева ВЫКЛ.
  • ID 6 исключен, потому что он имеет состояние нагрева ВЫКЛ.

Ответы [ 2 ]

0 голосов
/ 16 мая 2018

Я думаю, что это лучше всего решить, используя функции Windows и отфильтрованный агрегат.

Для каждой строки добавьте число более поздних строк, имеющих state = 'OFF', а затем используйте только те строки, для которых это число равно 0.

Вам нужен подзапрос, потому что вы не можете использовать результат оконной функции в условии WHERE (WHERE оценивается перед оконными функциями).

SELECT id, state, date
FROM (SELECT id, state, date,
             count(*) FILTER (WHERE state = 'OFF')
                OVER (ORDER BY date DESC, state DESC) AS later_off_count
      FROM tab) q
WHERE later_off_count = 0;

 id | state |    date    
----+-------+------------
 10 | ON    | 2018-02-23
  9 | ON    | 2018-02-22
  8 | ON    | 2018-02-22
  7 | ON    | 2018-02-22
(4 rows)
0 голосов
/ 16 мая 2018

Используйте функцию LEAD с выражением CASE.

SQL Fiddle

Запрос 1 :

SELECT id, 
       heating_state, 
       dt 
FROM   (SELECT t.*, 
               CASE 
                 WHEN dt >= timestamp '2018-02-20' 
                      AND heating_state = 'ON' 
                      AND LEAD(heating_state, 1, heating_state) 
                            OVER ( 
                                  ORDER BY dt ) = 'ON' THEN 1 
                 ELSE 0 
               END on_state 
        FROM   t) s 
WHERE  on_state = 1

Результаты

| id | heating_state |                   dt |
|----|---------------|----------------------|
|  7 |            ON | 2018-02-22T00:00:00Z |
|  8 |            ON | 2018-02-22T00:00:00Z |
|  9 |            ON | 2018-02-22T00:00:00Z |
| 10 |            ON | 2018-02-23T00:00:00Z |
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...