Esper事件处理引擎_12_EPL 语法_5_Subqueries子查询

官方地址:http://www.espertech.com


Esper 事件引擎栏目:http://blog.csdn.net/xiaohulunb/article/category/2436609


EPL 语法代码见-GitHub代码地址:点击打开链接


涉及 Javabean,Listener,main 以 GitHub 包下为最新更,注释解释排版有问题可参考源码


Subqueries子查询语法

package com.framework_technology.esper.epl;

import com.framework_technology.esper.javabean.Apple;
import com.framework_technology.esper.javabean.Banana;
import com.framework_technology.esper.javabean.Yieldly;

/**
 * Subqueries子查询
 * <p>
 * 基本上与SQL 的写法类似。
 * <p>
 * API - 5.11. Subqueries
 *
 * @author wei.Li by 14-8-12.
 */
public class EPL_5_Subqueries {


    /**
     * 以下限制适用于子查询:
     * <p>
     * 1.子查询流定义必须定义一个数据窗口或其它视图,以限制子查询的结果,减少了保持子查询执行的事件数
     * 2.子查询只能从子句包含一个select子句,一个where子句和GROUP BY子句。 having子句,以及连接,外连接和输出速率限制在子查询中是不允许的。
     * 3.如果使用聚合函数在子查询时,请注意以下限制:
     * 3.1没有一个相关流(次)的性质可以在聚合函数中使用。
     * 3.2子选择流的特性都必须在聚合函数。
     *
     * @return epl[]
     */
    protected static String subqueries() {

        /**
         * 子查询结果作为外部事件的属性
         * Apple事件 的 id 与 当前窗口中的最后一个Banana 的price 作为结果集输出
         */
        String epl1 = "select id, (select price from " + Banana.CLASSNAME + ".std:lastevent()) as lastBanana_price from " + Apple.CLASSNAME;

        /**
         * 子查询关联外部事件的属性
         */
        String epl2 = "select * from " + Apple.CLASSNAME + " as Apple where 3 = " +
                "  (select price from " + Banana.CLASSNAME + ".std:unique(id) where id = Apple.id)";
        //每进入一个Apple 事件。查询 id 与当前窗口中Banana 按照std:unique(id)保留的所有唯一值,无一个匹配则输出 null
        String epl3 = "select id, (select price from " + Banana.CLASSNAME + ".std:unique(id) where id = apple.id) as price from " + Apple.CLASSNAME + " as apple";

        /**
         * 子查询内部事件作为外部事件的属性
         */
        String epl4 = "select (select * from " + Banana.CLASSNAME + ".std:lastevent()) as banana from " + Apple.CLASSNAME;

        /**
         * 子查询中应用聚合函数
         */
        String epl5 = "select * from " + Apple.CLASSNAME + " where price > (select max(price) from " + Banana.CLASSNAME + "(id='Banana_Id').std:lastevent())";
        return epl4;
    }


    /**
     * The 'exists' Keyword
     *
     * @return epl
     */
    protected static String exists() {
        String epl1 = "select * from " + Apple.CLASSNAME + " as RFID " +
                "  where exists (select * from " + Banana.CLASSNAME + ".std:unique(id) where id = RFID.id)";
        return epl1;
    }


    /**
     * The 'in' and 'not in' Keywords
     *
     * @return epl
     */
    protected static String in_notin() {
        String epl1 = "select * from " + Apple.CLASSNAME + " as RFID " +
                "  where RFID.id in (select id from " + Banana.CLASSNAME + ".std:unique(id))";
        return epl1;
    }


    /**
     * The 'any' and 'some' Keywords
     * any :至少大于结果集的一个 or 连接
     * some:至少等于结果集的一个 or 连接
     *
     * @return epl
     */
    protected static String any_some() {
        String epl1 = "select * from " + Apple.CLASSNAME + " as RFID " +
                "  where RFID.id < any(select id from " + Banana.CLASSNAME + ".win:keepall())";
        return epl1;
    }


    /**
     * The 'all' Keyword
     * all:必须小于所有结果集的值才满足 and 连接
     *
     * @return epl
     */
    protected static String all() {
        String epl1 = "select * from " + Apple.CLASSNAME + " as RFID " +
                "  where RFID.id < all(select id from " + Banana.CLASSNAME + ".win:keepall())";
        return epl1;
    }


    /**
     * EPL也同样支持join,并且包含了full outer join / left outer join / right outer join / inner join等。
     * 和sql基本无差别。
     *
     * @return epl
     */
    protected static String join() {
        /**
         * inner join
         在没有任何关键字的修饰下,即为默认join方式,也就是inner join。
         必须等到所有join的事件都到了才可能输出,因为要是有where关联两个事件,得满足where条件了才能输出
         如果只有Apple到或者Banana到都不会输出内容。std:lastevent是一种data window。如果不加特殊修饰的话(特殊修饰?下面会告诉你),
         事件必须有data window或者view修饰,否则会出现语法错误。
         当然,不同的事件可以用不同的data window修饰,并没有规定要一样。
         */
        String epl1 = "select * from " + Apple.CLASSNAME + ".std:lastevent(), " + Banana.CLASSNAME + ".std:lastevent()";

        /**
         * full outer join
         上面看到的默认join方式是要求所有join的事件都必须到达引擎才会输出,并且join的事件之间通过where子句设置了条件判断,
         还得到达的两个事件满足条件了才能输出,而full outer join正好解决了这个问题,不管哪个事件到达,不管是否符合条件,都会输出。

         输出结果有4种可能:
         a.当只有Apple事件到达,没有满足join条件,会输出Apple事件,且Banana事件为null。
         b.当只有Banana事件到达,没有满足join条件,会输出Banana事件,且Apple事件为null。
         c.当两个事件都到达了,且没有满足join条件,即price不相等,则a,b情况各出现一次。
         d.当两个事件都到达了,且满足join条件,即price相等,即可输出满足条件的事件。
         所以说不管什么情况下,当前进入的事件都会输出,至于join的那个事件,满足即输出事件,不满足即输出null。
         */
        String epl2 = "select * from " + Apple.CLASSNAME + ".std:lastevent() as o full outer join " + Banana.CLASSNAME + ".std:lastevent() as b on o.price = b.price";

        /**
         * left outer join
         full outer join输出了所进入的所有事件,不满足join条件的就输出null,
         而left outer join则规定关键字左边的事件可以即刻输出,而关键字右边的事件必须满足join条件才可输出。

         因为Apple事件在left outer join的左边,所以他的输出不受join条件的限制,即事件到来该怎么输出怎么输出。
         但是Banana就不同,由于有join条件限制,即两个事件的price要相等,所以如果Banana事件到达的时候,
         如果没有满足条件的Apple事件,则Banana事件是不会输出的。(注意:输出null也算输出,这里是null都不会输出,即不触发listener)
         */
        String epl3 = "select * from " + Apple.CLASSNAME + ".std:lastevent() as pi left outer join " + Banana.CLASSNAME + ".std:lastevent() as pe on pi.price = pe.price";

        /**
         * right outer join
         和left outer join相反,在关键字右边的事件不受join条件约束,而左边的事件必须满足join条件才可输出。具体例子我就不举了,大家可以写两个句子试试。

         此外,在使用以上4种join的时候,可以多种join混用。
         on后面的表达式是join的限制条件,且只能用“=”,如果想用其他操作符,则必须放到where子句中,这点尤其要注意。
         多个限制条件只能用and连接,不能用逗号,且限制的事件也要一样。
         */
        String epl4 = "select * from " + Yieldly.CLASSNAME + ".std:lastevent() as a " +
                "     left outer join " + Banana.CLASSNAME + ".std:lastevent() as b on a.price = b.price " +
                "     full outer join " + Apple.CLASSNAME + ".std:lastevent() as o on o.price = a.price";
        /**
         * // a,b分别是两个事件的别名

         // 正确写法
         ……on a.price = b.price and a.size = b.size……

         // 错误写法1:不能用逗号连接
         ……on a.price = b.price, a.size = b.size……

         // 错误写法2:必须针对同样的事件进行限制(c是另一个事件的别名)
         ……on a.price = b.price and a.size = c.size……

         */


        /**
         * Unidirectional Join
         之前说到,如果不加特殊修饰,则join的事件都需要data window或者view修饰,目的是为了暂存事件以便等待满足条件的事件并执行join。
         如果想让某个事件到来时直接触发join,不需要暂存,也就是不需要data window或者view修饰,则需要加上一个特殊关键字——unidirectional。

         epl5的意思是:维持最新的Banana事件,直到一个和Banana的price相等的Apple事件到来时输出两者。
         由于有unidirectional的修饰,表明Apple事件是即时触发join操作,也就是说进入此EPL的Apple事件是无状态的。
         所以当Apple事件到来时,如果没有price相等的Banana,则什么输出也没有,即使下一个Banana事件的price和之前来的Apple的price相等也不会有输出,
         因为那个Apple事件已经从这个句子的上下文中移除了。
         */
        String epl5 = "select * from " + Apple.CLASSNAME + " as a unidirectional, " + Banana.CLASSNAME + ".std:lastevent() as b where a.price = b.price";
        /**
         * unidirectional使用很简单,但是也有其限制:
         1.在一个join句子中,unidirectional关键字只能用于一个事件流。
         2.用unidirectional修饰的事件流,不能通过esper的查询api查出来,因为该事件流是无状态的,不会暂存在引擎中,所以就没法查了。(关于查询api,后面的章节会详说)
         3.使用了unidirectional修饰的事件流就不能再用data window或者view修饰了,也就是说他们是互斥的。
         */
        
        return epl5;
    }

}


转载于:https://my.oschina.net/huluerwa/blog/311310

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值