1. 程式人生 > >Esper學習之九:EPL語法(五)

Esper學習之九:EPL語法(五)

轉載請註明出處:http://blog.csdn.net/luonanqin

       暫停更新三個多月,轉眼間就2014年了。年底相信都是大家最忙碌的時候,我也不例外,以至於真的是沒騰出手來繼續更新,好在年初這段時間可以休息一陣了,所以趕著這段時間空閒就多寫點吧。本來想先寫view,pattern這些常用的內容以滿足大部分人的需求,但是考慮到這些章節有涉及到前面章節的知識,所以我覺得基礎還是要學的,不能還沒學會走就想跑,否則可能會摔得很慘哦。

       本篇的內容主要包括了Subquery(也就是子查詢)和Join,內容不少,但是不難,基本上和sql差不太多。

1.Subquery

EPL裡的Subquery和sql的類似,是否比sql的用法更多我不得而知,畢竟本人是sql菜鳥,只在where語句裡用過子查詢。廢話不多說,先上幾個Subquer的簡單用法:

子查詢結果作為外部事件的屬性

  1. select assetId, (select zone from ZoneClosed.std:lastevent()) as lastClosed from RFIDEvent  
上面的例子是說返回當前RFIDEvent的assetId屬性值和最新ZoneClosed事件的zone屬性值,且以lastClosed作為zone的別名。

子查詢關聯外部事件的屬性

  1. select * from RfidEvent as RFID where 'Dock 1' = (select name from Zones.std:unique(zoneId) where zoneId = RFID.zoneId)  
子查詢語句中的where條件可以應用RFID的屬性,即內部的zoneId=RFID.zoneId
  1. select zoneId, (select name from Zones.std:unique(zoneId) where zoneId = RFID.zoneId) as name from RFIDEvent  
關聯外部事件屬性的同時也可以作為外部事件的屬性返回。

子查詢內部事件作為外部事件的屬性

  1. select (select * from MarketData.std:lastevent()) as md from SuperMarket  

每進入一個SuperMarket事件就返回最新的MarketData事件作為屬性返回,別名為md

子查詢中應用聚合函式

  1. select * from MarketData where price > (select max(price) from MarketData(symbol='GOOG').std:lastevent())  
子查詢出得最大price和當前事件的price進行比較
  1. select * from OrderEvent oe where qty > (select sum(qty) from OrderEvent.win:time(1 hour) pd where pd.client = oe.client)  
子查詢得出qty的總和和當前事件的qty進行比較

Filter中使用子查詢

  1. select * from BarData(ticker='MSFT', closePrice < (select movAgv from SMA20Stream(ticker='MSFT').std:lastevent()))  
子查詢返回的movAgv和外部事件的屬性closePrice進行比較作為外部事件的一個filter

Pattern中使用子查詢

  1. select * from pattern [  
  2.   a=A -> b=B(bvalue = (select d_val from DNamedWindow as d where d.d_id = b.b_id and d.d_id = a.a_id))  
  3. ]  

pattern的含義可先不深究,這裡只要知道子查詢可以用在pattern中就行了。

Expression中使用子查詢(什麼是Expression?請看《Esper學習之五:EPL語法(一)》的第八點)

  1. expression subq {  
  2.     (select max(quantity) as maxq, min(quantity) as minq from OrderEvent.win:time(1 min))  
  3. }  
  4. select (quantity - minq) / (subq().maxq  - subq().minq) as prorated from OrderEvent  

以上就是子查詢的幾種簡單用法,不過有幾點注意事項是要各位悉知的:

1.子查詢的返回必須使用data window或者view來進行限制,控制子查詢使用的事件數(data window和view相當於具有某種功能性的事件集合)

2.子查詢語句只能由select子句,from子句以及where子句組成,其他的均不支援,比如group by,limit等

3.沒有關聯外部事件的子查詢語句也可以使用聚合函式

4.子查詢語句中的select子句必須對所有屬性使用聚合函式

5.在使用子查詢時,如果子查詢的事件和外部事件型別一樣,則事件到來時,先經過子查詢語句的處理,然後再經過外部語句的處理。如果包含了多個子查詢語句,則事件的處理順序規則較為複雜,本人暫時沒做研究。

針對第4點可能說得有些不明白,特此舉例說明下:

  1. class Apple {  
  2.     privateint price;  
  3.     privateint size;  
  4.     publicvoid setPrice(int price) {  
  5.         this.price = price;  
  6.     }  
  7.     publicvoid setSize(int size) {  
  8.         this.size = size;  
  9.     }  
  10.     publicint getPrice() {  
  11.         return price;  
  12.     }  
  13.     publicint getSize() {  
  14.         return size;  
  15.     }  
  16. }  
  17. class Fruit {  
  18. }  
  19. publicclass Test {  
  20.     publicstaticvoid main(String[] args) throws InterruptedException {  
  21.         EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider();  
  22.         EPAdministrator admin = epService.getEPAdministrator();  
  23.         String epl1 = "select (select sum(price), sum(size) from " + Apple.class.getName() + ".std:lastevent()) from " + Fruit.class.getName();  
  24.         /* 
  25.          * 當然,對不同的屬性使用不同的聚合函式也是可以的 
  26.          */
  27.         // String epl1 = "select (select sum(price), avg(size) from " + Apple.class.getName() + ".std:lastevent()) from " + Fruit.class.getName();
  28.         /* 
  29.          * 注意:size沒有使用聚合函式,會導致建立epl失敗。文件中註明了“The properties of the subselect stream must all be within aggregation functions”. 
  30.          * 即子查詢中的select子句使用聚合函式時,所查詢的屬性都要使用聚合函式 
  31.          */
  32.         // String epl1 = "select (select sum(price), size from " + Apple.class.getName() + ".std:lastevent()) from " + Fruit.class.getName();
  33.         admin.createEPL(epl1);  
  34.         System.out.println("Create epl successfully!");  
  35.     }  
  36. }  

除了上面的語法外,有幾個關鍵字也是需要大家注意的。

exists

這個exists和exist可不一樣,雖說也是用在where子句中(不僅僅是where子句),但是exists前面是沒有什麼待比較屬性的。語法如下:

  1. exists (subquery)  
如果exists後面的subquery有查詢結果,則返回true,如果沒有查詢結果就返回false。所以用在where子句中的示例如下:
  1. select * from Fruit as F where exists (select * from Apple.std:lastevent() where acount = F.fcount)  
既然exists語法返回的時布林值,那麼可不可以用工在Filter中呢?經本人測試,確實可以用。示例如下:
  1. select * from Fruit(exists (select * from Apple.win:keepall()))  
不過在使用exists有兩個注意點:

1.exists後面的子查詢語句一定要用圓括號括起來,遺漏的話會報語法錯誤。

2.exists後面的子查詢語句只能返回單列值。什麼叫單列值?比如:Apple有price和size屬性,那麼select price和select size都是返回的單列(即一列),select price, size就是多列(即兩列)。如果subquery中返回的大於一列,則會報multi-column錯誤。謹記!

in / not in

用法和sql的一樣,具體語法就不說了,直接看例子吧:

  1. // 當前進入的Apple事件的aPrice存在於過去十秒內進入的Fruit的fPrice即可返回  
  2. select * from Apple where aPrice in (select fPrice from Fruit.win:time(10 s))  

注意:從語法上說in/not in前面是expression,並沒有規定只能是屬性。比如:Apple有aPrice和aSize兩個int屬性,則where子句可以寫成"aPrice+aSize in ....."(這裡只是舉例,不expression不表示任何意思)

any / some / all

除了用in或者not in判斷屬性值是否存在於子查詢結果中,還可以使用any/some/all並配合一些比較符號與子查詢結果進行比較。語法如下:

  1. expression operator any/some/all (subquery)  
  2. // operator包含:>=, !=, <>, <, <=, >, >=  
一個簡單的例子:
  1. // 如果當前Apple事件的aPrice小於前十個Fruit中的任何一個fPrice,則返回此事件  
  2. select * from Apple where aPrice < any (select fPrice from Fruit.win:length(10))  
  3. // 如果當前Apple事件的aPrice小於前十個Fruit中的所有fPrice,則返回此事件  
  4. select * from Apple where aPrice < all (select fPrice from Fruit.win:length(10))  

some和any同義,所以用法也相同。既然一樣為什麼又要弄這麼個關鍵字,我也沒搞懂。。。

子查詢返回多列資料

子查詢可以返回單列資料,也可以返回多列資料。用法很簡單,只需要“."(點)就能找到每列的資料了。示例如下:

  1. select *,  
  2.   (select bid, offer from MarketData.std:unique(symbol) as md where md.symbol = oe.symbol) as bidoffer  
  3. from OrderEvent oe  
如上所示,子查詢語句中包含bid和offer兩列,並且這個語句的結果用bidoffer作為別名,所以要想得到bid和offer的具體資料只需要bidoffer.bid和bidoffer.offer即可,簡單吧。子查詢返回多行資料和返回多列資料類似,只不過資料會以陣列形式是返回。

2.Join

Join在sql裡是很常見的查詢方法,EPL也同樣支援,並且包含了full outer join / left outer join / right outer join / inner join等。和sql基本無差別。

inner join

在沒有任何關鍵字的修飾下,即為預設join方式,也就是inner join。必須等到所有join的事件都到了才可能輸出,因為要是有where關聯兩個事件,得滿足where條件了才能輸出。例如:

  1. select * from Orange.std:lastevent(), Banana.std:lastevent()  
如果只有Orange到或者Banana到都不會輸出內容。std:lastevent是一種data window。如果不加特殊修飾的話(特殊修飾?下面會告訴你),事件必須有data window或者view修飾,否則會出現語法錯誤。當然,不同的事件可以用不同的data window修飾,並沒有規定要一樣。

full outer join

上面看到的預設join方式是要求所有join的事件都必須到達引擎才會輸出,並且join的事件之間通過where子句設定了條件判斷,還得到達的兩個事件滿足條件了才能輸出,而full outer join正好解決了這個問題,不管哪個事件到達,不管是否符合條件,都會輸出。例如:

  1. select * from Orange.std:lastevent() as o full outer join Banana.std:lastevent() as b on o.price = b.price  
輸出結果有4種可能:

a.當只有Orange事件到達,沒有滿足join條件,會輸出Orange事件,且Banana事件為null。

b.當只有Banana事件到達,沒有滿足join條件,會輸出Banana事件,且Orange事件為null。

c.當兩個事件都到達了,且沒有滿足join條件,即price不相等,則a,b情況各出現一次。

d.當兩個事件都到達了,且滿足join條件,即price相等,即可輸出滿足條件的事件。

所以說不管什麼情況下,當前進入的事件都會輸出,至於join的那個事件,滿足即輸出事件,不滿足即輸出null。

left outer join

full outer join輸出了所進入的所有事件,不滿足join條件的就輸出null,而left outer join則規定關鍵字左邊的事件可以即刻輸出,而關鍵字右邊的事件必須滿足join條件才可輸出。示例如下:

  1. select * from Pink.std:lastevent() as pi left outer join Pear.std:lastevent() as pe on pi.price = pe.price  
因為Pink事件在left outer join的左邊,所以他的輸出不受join條件的限制,即事件到來該怎麼輸出怎麼輸出。但是Pear就不同,由於有join條件限制,即兩個事件的price要相等,所以如果Pear事件到達的時候,如果沒有滿足條件的Pink事件,則Pear事件是不會輸出的。(注意:輸出null也算輸出,這裡是null都不會輸出,即不觸發listener)

right outer join

和left outer join相反,在關鍵字右邊的事件不受join條件約束,而左邊的事件必須滿足join條件才可輸出。具體例子我就不舉了,大家可以寫兩個句子試試。

此外,在使用以上4種join的時候,可以多種join混用。比如:

  1. select * from Apple.std:lastevent() as a   
  2.      left outer join Banana.std:lastevent() as b on a.price = b.price   
  3.      full outer join Orange.std:lastevent() as o on o.price = a.price  
on後面的表示式是join的限制條件,且只能用“=”,如果想用其他操作符,則必須放到where子句中,這點尤其要注意。多個限制條件只能用and連線,不能用逗號,且限制的事件也要一樣。比如:
  1. // a,b分別是兩個事件的別名  
  2. 相關推薦

    Esper學習EPL語法

    轉載請註明出處:http://blog.csdn.net/luonanqin        暫停更新三個多月,轉眼間就2014年了。年底相信都是大家最忙碌的時候,我也不例外,以至於真的是沒騰出手來繼續更新,好在年初這段時間可以休息一陣了,所以趕著這段

    Esper學習EPL語法

    轉載請註明出處:http://blog.csdn.net/luonanqin         中秋三天,說閒也不閒,調調工作的程式碼,倒還解決不少問題。不過也是因為最近工作忙的緣故,Esper被我冷落不少日子了,趁著今天最後一天,趕緊寫一篇出來。         從

    Esper學習EPL語法

    轉載請註明出處:http://blog.csdn.net/luonanqin        2014是新的一年,正好也是本人的本命年。既然是本命年,看來今年也是本人興旺之年了。。。開了個小玩笑,同時也祝各位同行今年少調bug多漲工資,這才是最實際的。

    Esper學習筆記四EPL語法2

    1.select 查詢所有屬性或特定屬性 EPL的select和SQL的select很相近,SQL用*表示查詢表的所有欄位,而EPL用*表示查詢事件流的所有屬性值。SQL查詢某個欄位名,直接在select後跟欄位名就ok,EPL也是將要查詢的屬性名放在select之後。若查多個屬

    Esper學習筆記三EPL語法1

    1.EPL語法簡介 EPL全稱Event Processing Language,是一種類似SQL的語言,包含了SELECT, FROM, WHERE, GROUP BY, HAVING 和 ORDER BY子句,同時用事件流代替了table作為資料來源,並且能像SQL那樣join,fil

    Esper學習十一EPL語法

    轉載請註明出處:http://blog.csdn.net/luonanqin        元宵過後回公司上班,換了個部門,換了個領導,做的事也換了,不過Esper還是會繼續搞,所以部落格也會慢慢寫的,大家別急。^_^        上一篇說到了EPL如何訪問關係型資料

    Esper學習筆記EPL語法3

    1.Aggregation 類似於SQL中的聚合函式,EPL中聚合函式格式如下: aggregate_function([all|distinct] expression) aggregate_function就是聚合函式的名字,比如avg,sum等。expression通常是事件

    在Ubuntu上學習OpenStack網絡計算節點上網絡補充配置

    分享 ini onf stack -a ubunt con openstac bubuko (註意:前面已經為計算+網絡節點配置了兩塊網卡eth0和eth1) v 執行如下命令: sudo ovs-vsctl add-br br-eth1 sudo ovs-vsctl ad

    WebRTC學習攝像頭的捕捉和顯示

    分享 註意 conn con wid pre rac art 升級版本 較新的WebRTC源代碼中已經沒有了與VoiceEngine結構相應的VidoeEngine了,取而代之的是MeidaEngine。MediaEngine包括了Medi

    機器學習支持向量機核函數和KKT條件的理解

    麻煩 ron 現在 調整 所有 核函數 多項式 err ges 註:關於支持向量機系列文章是借鑒大神的神作,加以自己的理解寫成的;若對原作者有損請告知,我會及時處理。轉載請標明來源。 序: 我在支持向量機系列中主要講支持向量機的公式推導,第一部分講到推出拉格朗日對偶函數的對

    機器學習支持向量機支持向量機的公式推導

    根據 監督式 art 通用 利用 哪些 這就是 在線 方法 註:關於支持向量機系列文章是借鑒大神的神作,加以自己的理解寫成的;若對原作者有損請告知,我會及時處理。轉載請標明來源。 序: 我在支持向量機系列中主要講支持向量機的公式推導,第一部分講到推出拉格朗日對偶函數的對偶因

    C++系統學習順序容器

      元素在順序容器中的順序與其加入容器時的位置相對應。關聯容器中元素的位置由元素相關聯的關鍵字值決定。所有容器類都共享公共的介面,不同容器按不同方式對其進行擴充套件。   一個容器就是一些特定型別物件的集合。順序容器為程式設計師提供了控制元素儲存和訪問順序的能力。 1. 順序容器概述 容器的兩種效能: 向容

    Keras學習3迴歸問題boston_housing資料為例

         本實驗使用boston_housing資料集對房價資料進行迴歸分析,資料來自1970年代,波斯頓周邊地區的房價,是用於機器學習的經典資料集。該資料集很小,共計506條資料,分為404個訓練樣本和102個測試樣本,因此需要採用K-Fold,這裡取K=4。每條資料包含1

    深度學習正則化系列2資料集增強資料增廣

    讓機器學習模型泛化得更好的最好辦法是使用更多的資料進行訓練。當然,在實踐中,我們擁有的資料量是很有限的。解決這個問題的一種方法是建立假資料並新增到訓練集中。對於一些機器學習任務,建立新的假資料相當簡單。對分類來說這種方法是最簡單的。分類器需要一個複雜的高維輸入

    強化學習雙臂賭博機Two-armed Bandit

    本文是對Arthur Juliani在Medium平臺釋出的強化學習系列教程的個人中文翻譯,該翻譯是基於個人分享知識的目的進行的,歡迎交流!(This article is my personal translation for the tutorial wri

    MQTT的學習Mosquitto發布-訂閱2

    creat 訂閱模式 pub 測試 方法 ssa clientm art ble 在《MQTT的學習之Mosquitto安裝&使用(1)》一文末尾,我已經模擬了發布-訂閱模式,只是那時在服務器直接模擬的,並不是java代碼模擬的。下面貼出Java代碼 1、首先引入依

    機器學習SVM初解與淺析:最大距離

    機器學習 svm 最大距離 2 / ||w|| 這段時間在看周誌華大佬的《機器學習》,在看書的過程中,有時候會搜搜其他人寫的文章,對比來講,周教授講的內容還是比較深刻的,但是前幾天看到SVM這一章的時候,感覺甚是晦澀啊,第一感覺就是比較抽象,特別是對於像本人這種I

    機器學習SVM初解與淺析:

    機器學習 svm 最大距離 2 / ||w||sdsshngshan‘gccha 這段時間在看周誌華大佬的《機器學習》,在看書的過程中,有時候會搜搜其他人寫的文章,對比來講,周教授講的內容還是比較深刻的,但是前幾天看到SVM這一章的時候,感覺甚是晦澀啊,第一感覺就

    java基礎知識學習--------枚舉類型1

    blog 枚舉類型 csdn 相同 名稱 枚舉類 java string pac 枚舉類型的概念: 1 /** 2 * 目的:枚舉類型 3 * @author chenyanlong 4 * 日期:2017/10/22 5 * 網址:http://blo

    前端學習入門-angular2-Typescript基本語法

    moved subst 一個 super clas color 模式 值類型 tin   接口   接口的創建 interface labelValue{ label:string; }   //創建函數對接口進行調用 labelObj是