(PostgreSQL 8.4)
继续前面的示例,我希望进一步了解使用Window函数进行间隙和孤岛处理的理解。请考虑下表和数据:
CREATE TABLE T1
(
id SERIAL PRIMARY KEY,
val INT, -- some device
status INT -- 0=OFF, 1=ON
);
INSERT INTO T1 (val, status) VALUES (10, 0);
INSERT INTO T1 (val, status) VALUES (11, 0);
INSERT INTO T1 (val, status) VALUES (11, 1);
INSERT INTO T1 (val, status) VALUES (10, 1);
INSERT INTO T1 (val, status) VALUES (11, 0);
INSERT INTO T1 (val, status) VALUES (10, 0);
如前所述,设备会打开和关闭,这一次我希望提取一个特定的序列:
ON
不重复的新状态记录(同一设备连续两次)OFF
当前ON
设备的适当状态我能得到的最接近的是:
SELECT * FROM (
SELECT *
,lag(val, 1, 0) OVER (PARTITION BY status ORDER BY id) last_val
,lag(status, 1, -1) OVER (PARTITION BY val ORDER BY id) last_status
FROM t1
) x
WHERE (last_val <> val OR last_status <> status)
AND (status = 1 OR last_status <> -1)
ORDER BY id
这可以过滤出样本中不包含的更多虚假数据,但本质上是关于取出后续重复项(无论状态如何)和OFF
不匹配的头条记录。记录3
,4
,5
和6
返回,但我不想在第五,这是一个OFF
后一个新的里面传来ON
。因此,我需要跳过这个空白,并OFF
为当前处于活动状态的设备寻找下一个合适的设备。
正确过滤后,我想首先使用lead()
它来获取下一行的ID(想象一个时间戳),并过滤掉所有不是ON
状态的记录。我想这将需要三个嵌入式SELECT语句。这将使我清楚地了解设备处于活动状态的时间,直到发生另一次ON
或适当的转弯OFF
。
SELECT *
FROM (
SELECT *
,lag(val, 1, 0) OVER (PARTITION BY status ORDER BY id) AS last_val
,lag(status, 1, 0) OVER w2 AS last_status
,lag(next_id) OVER w2 AS next_id_of_last_status
FROM (
SELECT *, lead(id) OVER (PARTITION BY status ORDER BY id) AS next_id
FROM t1
) AS t
WINDOW w2 AS (PARTITION BY val ORDER BY id)
) x
WHERE (last_val <> val OR last_status <> status)
AND (status = 1
OR last_status = 1
AND ((next_id_of_last_status > id) OR next_id_of_last_status IS NULL)
)
ORDER BY id
除了我们已经拥有的之外,我们还需要有效的OFF开关。
一个OFF
如果有效的,如果该设备被切换开关ON
(前last_status = 1
)和下一个ON
之后的操作来了之后OFF
所讨论开关(next_id_of_last_status > id
)。
我们必须提供最后一个ON
操作的特殊情况,因此我们NULL
还要检查(OR next_id_of_last_status IS NULL
)。
将next_id_of_last_status
来自同一个窗口中,我们采取last_status
的。因此,我为显式窗口声明引入了其他语法,因此不必重复我自己:
WINDOW w2 AS (PARTITION BY val ORDER BY id)
并且我们需要更早地获得子查询(subquery t
)中最后一个状态的下一个ID 。
如果您已经了解了所有 这些内容 ,那么lead()
在此查询之上就可以毫无问题地打到最终目的地。:)
一旦变得如此复杂,就该切换到程序处理了。
这个相对简单的 plpgsql函数 改变了复杂窗口函数查询的性能,原因很简单,它只需要扫描整个表一次。
CREATE OR REPLACE FUNCTION valid_t1 (OUT t t1) -- row variable of table type
RETURNS SETOF t1 LANGUAGE plpgsql AS
$func$
DECLARE
_last_on int := -1; -- init with impossible value
BEGIN
FOR t IN
SELECT * FROM t1 ORDER BY id
LOOP
IF t.status = 1 THEN
IF _last_on <> t.val THEN
RETURN NEXT;
_last_on := t.val;
END IF;
ELSE
IF _last_on = t.val THEN
RETURN NEXT;
_last_on := -1;
END IF;
END IF;
END LOOP;
END
$func$;
称呼:
SELECT * FROM valid_t1();
问题内容: 我有一个简单的pojos(一个用户类)的列表,其中包含约15个简单字段和1个arrayList。这些代表用户,可能会将100或1000个用户存储在内存中,以避免每次都从外部系统检索它们。(我正在使用Ehcache) 我想通过junit测试知道K个用户列表使用了多少内存。 我的直觉是,即使像一千个这样的简单pojo也不会以任何方式威胁(换言之,小于100 Ko) 在此先感谢您的协助。我非
我在gradle中使用flyway,我在数据库控制台中手动运行了其中一个迁移,我想运行flyway,但告诉它忽略所有其他迁移版本之间的一个特定迁移版本。可以这样做吗?
问题内容: 在下面的查询中,我想在CASE的WHEN内以及在THEN之前添加AND条件,这是可能的吗? 例如WHEN’r’AND table1.name =“ jones”然后’非常高’ 问题答案: 您可以像这样重写语句以完成所需的操作 请注意,您需要在声明后删除。 这里的文件
问题内容: 很抱歉那个愚蠢的问题。如何在javascript切换大小写语言元素中为案件使用条件?像下面的示例一样,当变量<= 5和> 0 时,大小写应该匹配;但是,我的代码不起作用: 感谢您的任何建议! 问题答案: 这有效: 此答案的先前版本认为括号是罪魁祸首。实际上,括号在这里是无关紧要的-唯一必要的是您的case表达式必须为布尔值。 之所以起作用,是因为我们将给开关的值用作比较的依据。因此,同
我有一个视图寻呼机,它的适配器上有片断列表。这就是我想要实现的场景: 假设我们有4个片段:Fragment1 Fragment2 Fragment3 Fragment4 我想在从Fragment4中滑动时跳过fragment3。 任何帮助都是非常感谢的。非常感谢你
我有一个工作,处理项目的大块(1000个)。这些项目被封送到一个JSON有效负载中,并作为一个批处理发布到远程服务(在一个HTTP POST中所有1000个)。有时远程服务陷入困境,连接超时。我为此设置了跳过 如果一个块失败了,批处理重试这个块,但一次一个项目(为了找出是哪个项目导致了失败)但在我的情况下,没有一个项目导致了失败,这是整个块作为块成功或失败的情况,应该作为块重试(事实上,下降到单项