选择与PostgreSQL匹配条件的最新连续记录

时间:2018-05-16 15:02:46

标签: sql postgresql

我正在寻找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 |

我需要查找所有最近的连续记录,日期> gt; = 2018-02-20和heating_state ON,即ID为7,8,9,10的记录。我的主要问题是它们必须是连续

如需进一步澄清:

  • ID 1被排除,因为早于2018-02-20
  • ID 2被排除,因为其后是ID 3,其具有加热状态OFF
  • ID 3被排除,因为它具有加热状态OFF
  • ID 4被排除,因为它后面是ID 5,它已关闭加热
  • ID 5被排除,因为它具有加热状态OFF
  • ID 6被排除,因为它具有加热状态OFF

2 个答案:

答案 0 :(得分:3)

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

<强> Results

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

答案 1 :(得分:2)

我认为最好使用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)