在多个属性上分散不同的事件

时间:2019-01-31 14:15:11

标签: group-by stream distinct esper

我对Esper中的流语义有疑问。我的目的是仅输出具有成对不同属性的事件。此外,属性之间还必须保留时间条件(请参见Espers Interval Algebra Reference)。

示例语句:

insert into output_stream select a.*, b.*
from stream1#length(100) as a, stream2#length(100) as b
where a.before(b) or a.meets(b) or a.overlaps(b)

按对不同的属性表示,我要确保没有没有两个输出 o1, o2 其中 o1.a = o2.a or o1.b = o2.b。再举一个具体的例子,如果有结果的话

o1: (a = a1, b = b1),
o2: (a = a1, b = b2),
o3: (a = a2, b = b2),
o4: (a = a2, b = b1)

只能输出其中两个(例如o1和o3或o2和o4)。现在哪一个都不重要。

我想用NOT EXISTS子句来完成成对的不同属性,如下所示:

NOT EXISTS ( 
    select * from output_stream#length(100) as otherOutput 
    where a = otherOutput.a or b = otherOutput.b )

部分起作用,对于连续输出,断言o1.a = o2.a or o1.b = o2.b始终成立。

但是,当stream1首先传递多个“ a”,然后stream2传递一个与要同时连接两个“ a”的条件匹配的“ b”时,会有多个输出< em>一次。我的NOT EXISTS子句不涵盖此内容,因为在同一步骤中会出现具有相同“ b”的多个输出,因此它们尚未出现在output_stream中。

distinct关键字在这里不合适,因为它会一起检查所有属性,而不是成对检查。同样,在所有属性上使用简单的group by也不合适。我希望使用类似“在a上不同并且在b上不同”的标准,但是它不存在。

我可以使用嵌套的group by来解决此问题,在每个属性上进行分组

select first(*) from (select first(*) from output_stream group by a) group by b

但是根据一个评论,在流处理系统中没有明确定义的语义。因此,Esper不允许在查询的from部分进行子查询。

我需要的是一种方法,一次只强制输出一个输出,然后在每个其他输出上重新检查NOT EXISTS条件,或者以某种方式检查同时出现的输出彼此之间实际上将它们插入流中。

更新: 输出的时间不是很关键。 output_stream将由其他此类语句使用,因此我可以通过增加窗口的长度来解决延迟问题。 stream1stream2按照其startTimestamp属性的顺序传递事件。

1 个答案:

答案 0 :(得分:1)

create schema Pair(a string, b string);
create window PairWindow#length(100) as Pair;
insert into PairWindow select * from Pair;
on PairWindow as arriving select * from PairWindow as other  
  where arriving.a = other.a or arriving.b = other.b

这是一个使用命名窗口的示例自连接,该窗口保留了最后100对。

编辑:以上查询是为了我对原始要求的理解而设计的。以下查询是为新的澄清而设计的。它检查“ a”或“ b”是否具有先前的值(在最近的100个事件中,根据需要将#length(100)保留为空)

create schema Pair(a string, b string);
create window PairUniqueByA#firstunique(a)#length(100) as Pair;
create window PairUniqueByB#firstunique(b)#length(100) as Pair;

insert into PairUniqueByA select * from Pair;
insert into PairUniqueByB select * from Pair;

select * from Pair as pair
  where not exists (select a from PairUniqueByA as uba where uba.a = pair.a)
  and not exists (select a from PairUniqueByB as ubb where ubb.b = pair.b);