ヘッダーをスキップ
Oracle® CEP EPL 言語リファレンス
リリース 11gR1 (11.1.1)
B55579-01
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

2 EPL リファレンス : 句

この節では、以下のトピックについて説明します。

2.1 EPL 文で使用可能な句の概要

イベント処理言語 (EPL) の上位レベル BNF は以下のとおりです。

  [ INSERT INTO insert_into_def ]
    SELECT select_list
  { FROM stream_source_list /  MATCHING pattern_expression }
  [ WHERE search_conditions ]
  [ GROUP BY grouping_expression_list ]
  [ HAVING grouping_search_conditions ]
  [ ORDER BY order_by_expression_list ]
  [ OUTPUT output_specification ]

リテラル キーワードでは大文字と小文字が区別されません。以降の節では、それぞれの句について詳しく示します。組み込みの演算子と関数については、「第 3 章 EPL リファレンス : 演算子」および「第 4 章 EPL リファレンス : 関数」を参照してください。

2.2 SELECT

すべての EPL 文には SELECT 句が必要です。SELECT 句を使用して、ワイルドカード * ですべてのプロパティを選択するか、イベント プロパティおよび式のリストを指定できます。SELECT 句は、文でパブリッシュされる、または文から抽出される結果イベントのイベント タイプ (イベント プロパティの名前と型) を定義します。

SELECT 句では、文にアタッチされている更新リスナにイベントがポストされるしくみを制御する省略可能な ISTREAM および RSTREAM キーワードも提供されます。

SELECT 句の構文の概要を以下に示します。

  SELECT [RSTREAM | ISTREAM] ( expression_list | * )

以降の例では、イベント データのソースを定義する FROM 句を使用します。FROM 句については、節 2.3「FROM」で説明しています。

2.2.1 特定のイベント プロパティの選択

返される特定のイベント プロパティを選択するには :

  SELECT event_property [, event_property] [, ...] 
  FROM stream_def

次の文では、直前の 100 の株価表示イベントで、量のカウントと標準偏差が選択されます。

  SELECT COUNT, STDDEV(volume) 
  FROM StockTick RETAIN 100 EVENTS

2.2.2 式の使用

SELECT 句には 1 つまたは複数の式を含めることができます。

  SELECT expression [, expression] [, ...] 
  FROM stream_def

次の文では、株価表示イベントの直前 30 秒間の時間バッチで価格と量の乗算値が選択されます。

  SELECT volume * price 
  FROM StockTick RETAIN BATCH OF 30 SECONDS

2.2.3 イベント プロパティのエリアス

以下の構文で、イベント プロパティおよび式のエリアスを指定できます。

  SELECT [event_property | expression] AS identifier [,…]

次の文では、価格と量の乗算値が選択され、イベント プロパティの名前 volPrice が指定されます。

  SELECT volume * price AS volPrice 
  FROM StockTick RETAIN 100 EVENTS

2.2.4 すべてのイベント プロパティの選択

ストリーム内のすべてのイベント プロパティを選択する構文は以下のとおりです。

  SELECT * 
  FROM stream_def

次の文では、直前の 30 秒間のすべての StockTick イベント プロパティが選択されます。

  SELECT * 
  FROM StockTick RETAIN 30 SECONDS

結合文では、SELECT * 構文を使用すると、結合されたストリーム自身を表すイベントが含まれるイベント プロパティが選択されます。

SELECT 句ではワイルドカード * と式を組み合わせることもできます。この組み合わせにより、すべてのイベント プロパティのほか、SELECT 句の一部として含まれる追加の式で指定された計算値が選択されます。この例では、株価表示イベントのすべてのプロパティのほか、pricevolume という名前が指定された、価格と量により計算された乗算値が選択されます。

  SELECT *, price * volume AS pricevolume 
  FROM StockTick RETAIN ALL

2.2.5 ISTREAM および RSTREAM キーワードによる新しいイベントと古いイベントの選択

SELECT 句の省略可能な ISTREAM および RSTREAM キーワードは、文の更新リスナにポストされるイベント ストリームを定義します。いずれのキーワードも指定しない場合、エンジンでは挿入ストリームおよび削除ストリームの両方のイベントが文のリスナにポストされます。挿入ストリームはそれぞれの枠、ストリーム、または集約に入れられたイベントで構成され、削除ストリームはそれぞれの枠または変更された集約結果を離れたイベントで構成されます。挿入イベントおよび削除イベントについては、節 1.2.7「イベント シンク」でさらに詳しく説明しています。

ISTREAM キーワードを指定することにより、更新リスナに挿入ストリーム イベントのみをポストするようエンジンに通知できます。エンジンでは削除ストリーム イベントがポストされなくなります。RSTREAM キーワードを指定することにより、更新リスナに削除ストリーム イベントのみをポストするようエンジンに通知できます。エンジンでは挿入ストリーム イベントがポストされなくなります。

次の文では、30 秒の時間枠を離れるイベントのみが選択されます。

  SELECT RSTREAM * 
  FROM StockTick RETAIN 30 SECONDS

SELECT 句の ISTREAM および RSTREAM キーワードは、節 2.11「INSERT INTO」で説明しているとおり、INSERT INTO 句で使用可能な同じ名前のキーワードに対応します。SELECT 句のキーワードが文に対する更新リスナにポストされるイベント ストリームを制御するのに対し、INSERT INTO 句の同名のキーワードはエンジンによって他の文で使用できるようになるイベント ストリームを指定します。

2.3 FROM

すべての EPL 文には FROM または MATCHING 句のいずれかが必要です。FROM 句は、イベント データのソースとして 1 つまたは複数のイベント ストリームを指定します。MATCHING 句については、節 2.5「MATCHING」で説明しています。

  FROM stream_expression [ inner_join | outer_join ] 

inner_join ではストリーム式のカンマ区切りのリストとして指定します。

  (, stream_expression )*

outer_join の定義は以下のとおりです。

((LEFT|RIGHT|FULL) OUTER JOIN stream_expression ON prop_name = prop_name)*

内部結合については、節 2.3.1「内部結合」で、外部結合については、節 2.3.2「外部結合」で詳しく説明しています。

stream_expression はストリーム データのソースとして使用されるイベント タイプ名を定義します。より複雑なシナリオでは、ネストされた EPL 文としてのサブクエリ式、または JDBC データにアクセスするパラメータ化された SQL クエリを定義します。これらのすべてのケースで、stream_expression にはオプションとして他の式のあいまいなプロパティ名参照を修飾する識別子としてのエリアスと、残りのクエリで処理されるストリーム データの枠を定義する RETAIN 句を含むことができます。

  (stream_name | subquery_expr | param_sql_query) [[AS] alias]] [RETAIN retain_expr]
  subquery_expr: ( epl_statement )
  param_sql_query: database_name ('parameterized_sql_query')

subquery_expr はサブクエリまたはネストされた EPL 文を括弧で囲んで定義します。サブクエリは外部 EPL 文で処理されるイベント ストリーム データを事前にフィルタ処理するために使用されます。たとえば、次のクエリでは、外部 EPL クエリで処理されるデータは Reuters フィードからの StockTick イベントのみに制限されます。

  SELECT stockSymbol, AVG(price)
  FROM (SELECT * FROM StockTick WHERE feedName = 'Reuters' ) 
  RETAIN 1 MINUTE PARTITION BY stockSymbol
  GROUP BY stockSymbol

サブクエリは任意にネストできますが、INSERT INTO または OUTPUT 句を含むことはできません。上位レベルの EPL 文とは異なり、サブクエリ内では RETAIN 句を省略できます。サブクエリ式については、節 2.3.3「サブクエリ式」で詳しく説明しています。

param_sql_query はパラメータ化された SQL クエリを括弧で囲まれた引用符で指定し、これにより JDBC を通じてアクセス可能な参照および履歴データを取得できます。database_name はクエリが実行されるデータベースの名前を識別します。データベース接続の確立、接続の作成および切断の制御、およびクエリ結果のキャッシュ ポリシーの設定のためのコンフィグレーション情報はこのデータベース名に関連付けられています。パラメータ化された SQL クエリについては、節 2.3.4「パラメータ化された SQL クエリ」で詳しく説明しています。

RETAIN 句は、クエリ処理の前に FROM 句にリストされたストリームから読み取られるイベント データの量を定義します。保持の異なるポリシーが必要な場合は、ストリームごとに独自の RETAIN 句を指定できます。それ以外の場合、RETAIN 句は、すべてのストリームに適用されるように FROM 句の末尾に追加します。本質的に、RETAIN 句は FROM 句内で自身の前にあるすべてのストリームに適用されます。

たとえば、次の EPL 文では、StockTick イベントは 5 件保持され、News イベントは 3 件保持されます。

  SELECT t.stockSymbol, t.price, n.summary
  FROM StockTick t RETAIN 5 EVENTS, News n RETAIN 3 EVENTS
  WHERE t.stockSymbol = n.stockSymbol

ただし、次の EPL 文では、StockTick イベントは 4 件、News イベントは 4 件保持されます。

  SELECT t.stockSymbol, t.price, n.summary
  FROM StockTick t, News n RETAIN 4 EVENTS
  WHERE t.stockSymbol = n.stockSymbol

サブクエリ式の例外を除いて、すべてのストリーム ソースには RETAIN 句による制約が必要です。このため、上位レベルの EPL 文として FROM 句には少なくとも末尾に 1 つの RETAIN 句が含まれている必要があります。パラメータ化された SQL クエリからの外部データは RETAIN 句の影響を受けません。RETAIN 句については、節 2.4「RETAIN」で説明しています。

2.3.1 内部結合

FROM 句には 2 つ以上のイベント ストリームを含めることができるため、両方のストリームにより結果イベントが決定されます。2 つ以上のストリームのイベントを関連付けるために EPL が使用する結合条件は WHERE 句にリストされます。たとえば、結合されたストリーム ソースのいずれにもイベント データが発生しなかった場合など、条件が満たされない場合、出力は生成されません。

いずれかのイベント ストリームにイベントが到着した各時点で、2 つのイベント ストリームが結合され、WHERE 句に応じて出力イベントが生成されます。

この例では、2 つのイベント ストリームが結合されます。最初のイベント ストリームは、直前の 30 分間が保持される不正警告イベントから成ります。2 つ目のストリームは、直前の 30 秒が考慮される引き出しイベントです。これらのストリームは口座番号で結合されます。

  SELECT fraud.accountNumber AS accntNum, 
    fraud.warning AS warn, withdraw.amount AS amount,
    MAX(fraud.timestamp, withdraw.timestamp) AS timestamp, 
    'withdrawlFraud' AS desc
  FROM FraudWarningEvent AS fraud RETAIN 30 MIN,
       WithdrawalEvent AS withdraw RETAIN 30 SEC
  WHERE fraud.accountNumber = withdraw.accountNumber

2.3.2 外部結合

EPL では、個数制限のないイベント ストリーム間の左外部結合、右外部結合、および完全外部結合がサポートされています。ストリーム ソースにイベント データが存在しない場合でも、LEFTRIGHT、または FULL 修飾子に応じて出力が生成されます。

外部結合が左外部結合の場合、句の左側にあるストリームの各イベントについて出力イベントが発生します。たとえば、下の左外部結合では、イベント ストリーム OrderList 内のイベントにイベントが一致しない場合であっても、ストリーム RfidEvent 内の各イベントの出力が取得されます。

  SELECT * 
  FROM RfidEvent AS rfid 
                 LEFT OUTER JOIN
             OrderList AS orderlist 
                 ON rfid.itemId = orderList.itemId
  RETAIN 30 SECONDS

同様に、結合が右外部結合の場合、句の右側にあるストリームの各イベントについて出力イベントが発生します。たとえば、下の右外部結合では、イベント ストリーム RfidEvent 内のイベントにイベントが一致しない場合であっても、ストリーム OrderList 内の各イベントの出力が取得されます。

  SELECT * 
  FROM RfidEvent AS rfid 
                 RIGHT OUTER JOIN
             OrderList AS orderlist 
                 ON rfid.itemId = orderList.itemId
  RETAIN 30 SECONDS

すべてのタイプの外部結合では、結合条件が満たされない場合、到着したイベントのイベント プロパティで選択リストが計算され、他のすべてのイベント プロパティは null と見なされます。

  SELECT * 
  FROM RfidEvent AS rfid 
                 FULL OUTER JOIN
             OrderList AS orderlist 
                 ON rfid.itemId = orderList.itemId
  RETAIN 30 SECONDS

外部結合の最後のタイプは完全外部結合です。完全外部結合では、いずれかのイベント ストリームにイベントが到着した各時点で、1 つまたは複数の出力イベントが生成されます。下の例では、RfidEvent または OrderList イベントが到着すると、1 つまたは複数の出力イベントが生成されます。

2.3.3 サブクエリ式

サブクエリ式は、FROM 句の括弧内にネストされた EPL 文です。サブクエリには INSERT INTO 句または OUTPUT 句を含めることはできません。また、上位レベルの EPL 文とは異なり、RETAIN 句は省略可能です。

サブクエリ式は、式を包含している EPL 文の前に実行されるため、外部の文で処理されるイベント データを事前にフィルタ処理する際に便利です。たとえば、次のクエリでは、直前の 100 の StockTick イベントで特定の銘柄の変化する平均値が計算されます。

  SELECT AVG(price)
  FROM (SELECT * FROM StockTick WHERE stockSymbol = 'ACME' ) 
  RETAIN 100 EVENTS

WHERE 句が外部クエリ内に置かれた場合は、他の銘柄記号の StockTick イベントが枠に入れられ、平均価格の計算に使用されるイベント数が軽減されます。

また、サブクエリを使用する目的には、a) 内部のイベント ソース構造を外部 EPL 文で必要とされる構造に変換する場合、または b) 複数のイベント ストリームを結合して単一のイベント ストリームを形成する場合、があります。これにより、INSERT INTO 句を使用して複数の EPL 文を接続する代わりに、単一の EPL 文を使用できます。たとえば、次のクエリでは、EventA および EventB からのトランザクション データが結合され、結合されたデータが外部クエリで使用されます。

  SELECT custId, SUM(latency)
  FROM (SELECT A.customerId AS custId, A.timestamp -B.timestamp AS latency
                FROM EventA A, EventB B
                WHERE A.txnId = B.txnId)
  RETAIN 30 MIN
  GROUP BY custId

サブクエリ自身にサブクエリを含めることができるため、任意のレベルのネストが許可されます。

2.3.4 パラメータ化された SQL クエリ

パラメータ化された SQL クエリでは、EPL 文に含まれる SQL を介して、JDBC を通じてアクセス可能な参照および履歴データに対するクエリを実行できます。EPL からこれらのデータ ソースにアクセスできるようにするには、いくつかのコンフィグレーションが必要です。

現在適用される制限には、以下のものがあります。

  • 1 つのイベント ストリームのみを 1 つの SQL クエリに結合できます。2 つ以上のイベント ストリームと SQL クエリの結合はサポートされていません。

  • SQL クエリのストリームでは RETAIN 句に指定された制限が無視されます。つまり、SQL クエリに時間ベースまたはイベント ベースの枠を作成することはできません。ただし、INSERT INTO 構文を使用して、結合の結果を他の文に対して使用可能にできます。

  • データベース ソフトウェアではコンパイル時に文のメタデータを提供する JDBC プリペアド ステートメントをサポートしている必要があります。ほとんどの主なデータベースではこの機能が提供されます。

クエリ文字列は一重または二重引用符を付けて括弧で囲みます。クエリには 1 つまたは複数の置換パラメータを含めることができます。クエリ文字列は変更されずにデータベース ソフトウェアに渡されるため、ストアド プロシージャ コールを含む、データベースで認識される任意の SQL クエリ構文を作成できます。

SQL クエリ文字列の置換パラメータは ${event_property_name} という形式を取ります。エンジンでは文の実行時に event_property_name が結合イベント ストリーム内のイベントで提供される実際のイベント プロパティ値に解決されます。

エンジンでは SQL クエリの出力カラムの型がデータベース ソフトウェアで返される文の結果セットのメタデータによって決定されます。実際のクエリ結果は java.sql.ResultSetgetObject を通じて取得されます。

下の EPL 文の例では、CustomerCallEvent イベントで構成されるイベント ストリームが、データベース MyCustomerDB およびテーブル Customer に対する SQL クエリの結果と結合されます。

  SELECT custId, cust_name 
  FROM CustomerCallEvent,
  MyCustomerDB (' SELECT cust_name FROM Customer WHERE cust_id = ${custId} ')
  RETAIN 10 MINUTES

上の例では CustomerCallEventcustId というイベント プロパティが提供されていると想定します。SQL クエリでは Customer テーブルから顧客名が選択されます。SQL の WHERE 句では Customer テーブル カラムの cust_id が各 CustomerCallEvent イベントの custId の値と照合されます。エンジンでは新しい CustomerCallEvent が検出されるたびに SQL クエリが実行されます。

指定の顧客 ID のカラムが SQL クエリで返されなかった場合、エンジンは出力イベントを生成しません。カラムが返された場合、エンジンでは SQL クエリで返されるカラムごとに 1 つの出力イベントが生成されます。次の節で説明しているように、外部結合を使用して、SQL クエリでカラムが返されない場合でもエンジンで出力イベントが生成されるかどうかを制御できます。

次の例では、イベント ストリーム CustomerCallEvent に 30 秒の時間枠が追加されます。また、選択されたプロパティの名前が customerName および customerId に変更されます。これは、EPL クエリの SELECT 句で SQL クエリによるカラム名の指定がどのように使用されるかを示しています。この例では AS キーワードを介して明示的なストリーム名を使用します。

  SELECT customerId, customerName 
  FROM CustomerCallEvent AS cce RETAIN 30 SECONDS,
    MyCustomerDB 
    ("SELECT cust_id AS customerId, cust_name AS customerName 
      FROM Customer WHERE cust_id = ${cce.custId}") AS cq 

時間枠などの任意の枠では、イベントが枠に入ると挿入イベントが生成され、イベントが枠を離れると削除イベントが生成されます。エンジンでは挿入ストリームおよび削除ストリームの両方のケースで、各 CustomerCallEvent に対して指定の SQL クエリが実行されます。パフォーマンスの最適化として、SELECT 句の ISTREAM または RSTREAM キーワードを使用して、挿入イベントまたは削除イベントのみを結合するようエンジンに通知し、SQL クエリの実行数を軽減できます。

パラメータ化された SQL クエリを外部結合で使用することもできます。SQL クエリで行が返されるかどうかにかかわらず各イベントの出力イベントが必要な場合は、次の文のように、左外部結合を使用します。SQL クエリで行が返されない場合は、結合の結果によって選択されたプロパティに null 値が挿入されます。

  SELECT custId, custName 
  FROM CustomerCallEvent AS cce
    LEFT OUTER JOIN
    MyCustomerDB 
      ("SELECT cust_id, cust_name AS custName
        FROM Customer WHERE cust_id = ${cce.custId}") AS cq
    ON cce.custId = cq.cust_id
  RETAIN 10 MINUTES

上の文では、SQL クエリで行が返されない場合でも、SQL クエリで選択されたすべてのカラムを含む出力イベントが各 CustomerCallEvent に対して常に少なくとも 1 つ生成されます。外部結合では ON 式が必要なことに注意してください。ON は SQL クエリで返された行に対する追加のフィルタとして動作します。

2.4 RETAIN

FROM 句には少なくとも 1 つの RETAIN句が必要です。RETAIN 句は FROM 句で自身の前にリストされているすべてのストリーム ソースに適用されます。概念的に、クエリの実行対象となる各ストリーム ソースのイベント データの枠が定義されます。RETAIN 句の構文は以下のとおりです。

  RETAIN
  ( ALL [EVENTS] ) |
  ( [BATCH OF] 
    ( integer (EVENT|EVENTS) ) | ( time_interval (BASED ON prop_name)* )
    ( WITH [n] (LARGEST | SMALLEST | UNIQUE) prop_name )* 
    ( PARTITION BY prop_name )* )

RETAIN 句の各側面について、詳細を以下に示します。

2.4.1 すべてのイベントの保持

ストリーム ソースのすべてのイベントを保持するには、RETAINALL [EVENTS] を指定します。

  SELECT AVG(price) 
  FROM StockTick RETAIN ALL EVENTS

この場合、発生するすべての StockTick イベントに基づいて平均価格が計算されます。ただし、数量が大きいシナリオでの計算時に各イベント オブジェクトの全体または部分を保持する必要があるとメモリが不足する可能性があるため、このオプションは慎重に使用する必要があります。この例としては重み設定された平均値の計算などがあります。

2.4.2 枠のサイズの指定

クエリの実行時に保持されるイベント データの量を決定するには 2 つの方法があります。最初のオプションでは、保持されるイベントの最大数を指定します。たとえば、次のクエリでは、平均価格を計算する StockTick イベントが最大 100 件保持されます。

  SELECT AVG(price) 
  FROM StockTick RETAIN 100 EVENTS

新しい StockTick イベントが到着するたびに、最大 100 件のイベントを使用して平均価格が計算されます。

2 つ目のオプションでは、イベント データが収集される時間間隔を指定します。たとえば、次のクエリでは 1 分間相当の StockTick イベントが保持され、このデータに対して平均価格が計算されます。

  SELECT AVG(price) 
  FROM StockTick RETAIN 1 MINUTE

この場合、新しい StockTick イベントが到着するたびに平均価格が計算されます。ただし、1 分以上前に到着したイベントは枠から削除され、枠内の残りのイベントに基づいて平均価格が再計算されます。

2.4.3 バッチ枠とスライド枠の指定

デフォルトでは、イベント データが保持される枠はスライド枠です。スライド枠では、枠が一杯になると新しいイベントが枠に入るときに古いイベントが削除されます。スライド枠では、新しいイベントが枠に入れられた場合または古いイベントが枠を離れた場合、あるいはその両方の場合に、クエリが再実行されます。もう 1 つの方法としては、クエリ実行の前にイベント データのバッチを指定します。枠が一杯にならないとクエリは実行されません。それ以降は、枠がまた一杯になるまで新しいイベント データが再び収集されてから、クエリが再実行されます。

たとえば、次のクエリでは 100 件のイベントがバッチで収集された後、平均価格を計算するクエリが実行されます。

  SELECT AVG(price) 
  FROM StockTick RETAIN BATCH OF 100 EVENTS

実行後は、次の 100 件のイベントがバッチ収集されてからクエリが再実行されます。

スライド枠とバッチ枠の詳細については、節 1.3「処理モデル」を参照してください。

2.4.4 時間間隔の指定

RETAIN 句の時間間隔は、日数、時間、分、秒、またはミリ秒単位で指定します。

  time_interval: [day-part][hour-part][minute-part][seconds-part][milliseconds-part]
  day-part: number ("days" | "day")
  hour-part: number ("hours" | "hour" | "hr")
  minute-part: number ("minutes" | "minute" | "min")
  seconds-part: number ("seconds" | "second" | "sec")
  milliseconds-part: number ("milliseconds" | "millisecond" | "msec" | "ms")

時間間隔のいくつかの例を示します。

  10 seconds
  10 minutes 30 seconds
  20 sec 100 msec
  0.5 minutes
  1 day 2 hours 20 minutes 15 seconds 110 milliseconds

2.4.4.1 BASED ON 句

デフォルトでは、時間間隔の経過は内部システム クロックに基づいています。ただし、ときにはイベント プロパティのタイムスタンプの値に基づいた時間が必要になることもあります。この場合は、BASED ON 句を使用して long 型のタイムスタンプ値が含まれるプロパティ名を指定できます。この例では、StockTick イベントに long 型の timestamp プロパティが含まれていることが予期され、この値によってイベントの枠への参加と終了が制御されます。

  SELECT AVG(price) 
  FROM StockTick RETAIN 1 MINUTE BASED ON timestamp

BASED ON 句を使用する場合、FROM 句の各ストリーム ソースには関連付けられた timestamp プロパティが含まれている必要があり、そうでない場合は Oracle CEP によって例外が送出されます。

2.4.5 プロパティ名の指定

RETAIN 句ではプロパティは単純にプロパティ名を使用して参照されます。ただし、FROM 句の複数のストリーム ソースに同名のプロパティが含まれているためあいまいさが存在する場合は、エリアス名のプレフィックスを付け、ピリオドを後に付ける必要があります (SELECT 句で参照されるプロパティの動作と同じです)。

2.4.6 PARTION BY 句を使用した枠の分割

PARTITION BY 句を使用すると、リストされたプロパティのユニークな値に基づいて、枠をさらに複数の枠に分割できます。たとえば、次のクエリでは、ユニークな銘柄記号ごとに 3 件のイベントが保持されます。

  SELECT stockSymbol, price 
  FROM StockTick RETAIN 3 EVENTS PARTITION BY stockSymbol

これは概念的に SQL または EPL の GROUP BY 関数と同じです。ただし、PARTITION BY 句では枠のサイズと分割のみが制御され、GROUP BY 句のようにイベント データは集約されません。ただし、多くの場合、PARTITION BY 句は同じプロパティを指定して GROUP BY 句と共に使用します。

次の例は、PARTITION BYGROUP BY の間の対話を示しています。最初の例には PARTITION BY 句がありませんが、すべての銘柄記号にわたり合計 10 件のイベントが保持されます。

  SELECT stockSymbol, AVG(price) 
  FROM StockTick RETAIN 10 EVENTS
  GROUP BY stockSymbol

これらの 10 件のイベントに基づいてユニークな銘柄記号のセットごとに平均価格が計算されます。銘柄記号 AAA が枠に入れられた場合、BBB などの異なる銘柄記号は枠から離れます。これにより、AAA グループと BBB グループの両方の平均価格が変更されます。

2 つ目の例は PARTITION BY 句と GROUP BY 句を使用します。

  SELECT stockSymbol, AVG(price) 
  FROM StockTick RETAIN 10 EVENTS PARTITION BY stockSymbol
  GROUP BY stockSymbol

この場合、ユニークな銘柄記号ごとに 10 件のイベントが保持されます。銘柄記号 AAA が枠に入れられた場合は、その銘柄に関連付けられたサブ枠のみに影響し、異なる銘柄記号の他の枠は影響を受けません。このため、この場合は AAA の平均価格のみに影響します。

2.4.7 WITH 句を使用した最大/最小/ユニークな値の保持

WITH 句を使用すると、プロパティの最大値、最小値、およびユニークな値を枠内に保持できます。たとえば、2 つの最高値の株価を保持するには、次の文を使用します。

  SELECT stockSymbol, price 
  FROM StockTick RETAIN ALL WITH 2 LARGEST price

時間ベースの枠の場合、LARGEST または SMALLEST キーワードの前にある [n] 修飾子は保持される値の個数を決定します。たとえば、次の文では 1 分間で発生した 2 つの最小価格が保持されます。

  SELECT stockSymbol, price 
  FROM StockTick RETAIN 1 MINUTE WITH 2 SMALLEST price

この修飾子がない場合は、1 つの最大値または最小値が保持されます。

UNIQUE 修飾子により、特定のプロパティに対して同じ値を持つイベントのうち最新のイベントのみが枠に保持されます。たとえば、次のクエリでは、ユニークな銘柄記号ごとに直前の株価表示のみが保持されます。

  SELECT * 
  FROM StockTick RETAIN 1 DAY WITH UNIQUE stockSymbol

同じプロパティ値の古いイベントはエンジンにより古いイベントとしてポストされます。

2.5 MATCHING

すべての EPL 文には MATCHING または FROM 句のいずれかが必要です。MATCHING 句は EPL 文で使用されるイベントを決定するためのもう 1 つのメカニズムです。これにより、指定されたパターンを満たす 1 つまたは複数の一連のイベントの発生が検出されます。パターン式は、パターンを形成するイベント シーケンスを定義し、ANDOR、および FOLLOWED BY などの論理演算子で区切られたストリームへの参照で構成されます。節 2.4「RETAIN」で指定されているとおり、省略可能な RETAIN 句を使用して、一致したイベントが含まれる枠の特性を定義します。MATCHING 句は WHERE または HAVING 句よりも前に実行されます。

MATCHING 句の構文は以下のとおりです。

  MATCHING pattern_expression [RETAIN retain_clause]

pattern_expression の構文は以下のとおりです。

  [NOT|EVERY] stream_expression 
      ( ( AND | OR | [NOT] FOLLOWED BY ) stream_expression )* 
  [WITHIN time_interval]

NOT 演算子を使用してイベントの欠落を検出できます。EVERY 演算子を使用してパターン照合が一致した後に継続する場合の動作を制御できます。stream_expression は、オプションで変数にバインドされ括弧内の式でフィルタ処理される、ストリーム ソース名です。

  stream_expression: [var_name:=]stream_name [( filter_expression )]

また、stream_expressionpattern_expression にすることができ、これにより任意の複雑な式のネスト化が許可されます。

var_name は、照合が起動される発生中のイベント オブジェクトにバインドされます。これは、後に続くフィルタ式や、SELECTWHERE 句などの他の句で、他の任意のイベント プロパティのように参照されます。stream_name の後には、省略可能な、そのタイプの一致するイベントをフィルタ処理する括弧内の式が続きます。式はイベントを適切な枠に入れるための事前条件のように動作し、WHERE 句の式と同じ構文を持ちます。すでに一致したイベントと関連付けるために、式の内部では前にバインドされた変数が使用されます。

time_interval は、節 2.4.4「時間間隔の指定」で指定されている時間間隔であり、省略可能な WITHIN キーワードの後に置かれ、上記の式が条件を満たすまで待機する時間を決定します。

次の例では、カテゴリが "Perishable" で、10 秒以内に RFIDError が後に続き、id が一致した RFIDEvent オブジェクトの ID と一致する RFIDEvent イベントが参照されます。

  SELECT * 
  MATCHING a:=RFIDEvent(category="Perishable") 
      FOLLOWED BY RFIDError(id=a.id) WITHIN 10 seconds
  RETAIN 1 MINUTE

以降の節では、パターン照合の時相的な制約を表すために MATCHING 句で使用できる構文、セマンティクス、および追加の演算子について説明します。

2.5.1 FOLLOWED BY 演算子

FOLLOWED BY FOLLOWED BY 時相演算子は、複数のイベント条件が特定の順序で発生した場合に一致します。まず左側の式が true になる必要があり、その場合にのみ右側の式で一致するイベントが評価されることが指定されます。

たとえば、次のパターンではイベント A が検索され、これが検出された場合にイベント B が検索されます。

  A FOLLOWED BY B

イベント A の直後にイベント B が続く必要はありません。イベント A とイベント B の間で他のイベントが発生する場合でも、この式は true に評価されます。この動作が適切でない場合は、節 2.5.4「NOT 演算子」で説明している NOT 演算子を使用してください。

2.5.2 AND 演算子

AND 論理演算子では、式全体が true を返す前に両方のネストされたパターン式が true になる必要があります。MATCHING 句のコンテキストでは、演算子は複数のイベント条件が発生した場合に一致しますが、必ずしも特定の順序である必要はありません。

たとえば、次のパターンは、イベント A とイベント B の両方が見つかった場合に一致します。

  A AND B

パターンは、A の後に B が続く任意のシーケンスでいずれの順序でも一致します。また、A イベントの直後に B イベントが続く必要はありません。A イベントおよび B イベントの発生の間に他のイベントが発生してもこの式では true が返されます。

2.5.3 OR 演算子

OR 論理演算子では、式全体が true を返す前にいずれかの式が true になる必要があります。MATCHING 句のコンテキストでは、演算子は複数のイベント条件のいずれかが発生した場合に一致しますが、必ずしも特定の順序である必要はありません。

たとえば、次のパターンは、イベント A またはイベント B のいずれでも一致します。

  A OR B

次の例では、特定の価格を超える、または特定の量を超えるすべての株価表示が検出されます。

  StockTick(price > 1.0) OR StockTick(volume > 1000)

2.5.4 NOT 演算子

NOT 演算子は式の実際の値を否定します。MATCHING 句のコンテキストでは、演算子によってイベント条件の欠落が検出されます。

次のパターンでは、イベント B の前にイベント C が検出された場合は除いて、イベント A の後にイベント B が検出された場合にのみ一致します。

  ( A FOLLOWED BY B ) AND NOT C

2.5.5 EVERY 演算子

EVERY 演算子は、EVERY キーワードで修飾されたサブ式が true または false に評価された場合に、パターンのサブ式を再度開始するよう通知します。EVERY 修飾子を指定しない場合は、NOT 式の内部に含まれていないパターン内の最初のイベント ストリームのソースに暗黙的な EVERY 演算子が修飾子として挿入されます。

EVERY 演算子は包含されているパターンのサブ式のファクトリのように動作します。含まれているパターンのサブ式が発動し、イベントのチェックを終了すると、EVERY によって同じイベントまたはイベント セットの以降の発生をリスンする新しいパターンのサブ式が開始されます。

EVERY 演算子内のパターンのサブ式が true になるたびに、エンジンでは新しいアクティブなサブ式が開始され、それ以降のイベント、またはパターンのサブ式に一致するタイミング条件が参照されます。

以下のようなイベント シーケンスの例を考えます。

A1 B1 C1 B2 A2 D1 A3 B3 E1 A4 F1 B4

表 2-1 例 EVERY 演算子

説明
EVERY ( A FOLLOWED BY B )

イベント A とその後に続くイベント B が検出されます。B が発生した時点でパターンが一致し、パターン照合が再開されてイベント A が再び検索されます。

組み合わせ {A1, B1}B1 で一致します。

組み合わせ {A2, B3}B3 で一致します。

組み合わせ {A4, B4}B4 で一致します。

EVERY A FOLLOWED BY B

パターンはすべてのイベント A とその後に続くイベント B で発動します。

組み合わせ {A1, B1}B1 で一致します。

組み合わせ {A2, B3} および {A3, B3}B3 で一致します。

組み合わせ {A4, B4}B4 で一致します。

EVERY A FOLLOWED BY EVERY B

パターンはすべてのイベント A とその後に続くすべてのイベント B で発動します。つまり、イベント A の後にイベント B が来るすべての組み合わせです。

組み合わせ {A1, B1}B1 で一致します。

組み合わせ {A1, B2}B2 で一致します。

組み合わせ {A1, B3}{A2, B3} および {A3, B3}B3 で一致します。

組み合わせ {A1, B4}{A2, B4}{A3, B4} および {A4, B4}B4 で一致します。


これらの例では、パターン式に一致するイベントの複数の組み合わせでパターンが発動できることを示しています。

相互に続く 3 つのイベントに一致するサブ式で EVERY 演算子を使用する場合を考えます。

  EVERY (A FOLLOWED BY B FOLLOWED BY C)

パターンでは最初にイベント A が検索されます。イベント A が到着すると、イベント B が検索されます。イベント B の到着後、イベント C が検索されます。最終的にイベント C が到着するとパターンが一致します。エンジンではイベント A の検索が再開されます。

イベント B とイベント C の間に 2 つ目のイベント A2 が到着すると想定します。パターンはその時点でイベント C を探しているため、A2 は完全に無視されます。前の例で見てきたとおり、EVERY 演算子ではサブ式が発動された場合にのみ、サブ式 A FOLLOWED BY B FOLLOWED BY C が再開されます。

次の文では、EVERY 演算子はサブ式全体ではなく、A イベントにのみ適用されます。

  EVERY A FOLLOWED BY B FOLLOWED BY C

このパターンでは、イベント A が到着するタイミングにかかわらず、すべてのイベント A についてその後にイベント B とイベント C が続く場合にパターンが一致します。これは、AND NOT 構文や RETAIN 構文と共に使用してイベントが枠内にとどまる期間に制約を設けない限り、多くの場合に実用的でなくなります。

2.5.6 WITHIN 演算子

WITHIN 修飾子の動作はストップウォッチと同じです。関連付けられているパターン式が指定の時間内に true にならなかった場合、エンジンでは false として評価されます。WITHIN 修飾子は、節 2.4.4「時間間隔の指定」で指定されているとおり、時間間隔をパラメータとして受け取ります。

このパターンは、文の作成後 5 秒以内に A イベントが到着すると発動します。

  A WITHIN 5 SECONDS

このパターンは 5 秒以内に到着するすべての A イベントで発動します。

このパターンは、次の 5 秒間の任意の 1 つの A または B イベントに一致します。

  (A or B) WITHIN 5 SECONDS

このパターンは、相互に 10 秒以内に発生する任意の 2 つのエラーに一致します。

  A(status='ERROR') FOLLOWED BY B(status='ERROR') WITHIN 10 SECONDS

このパターンは、10 秒以内に Status イベントが発生しない場合に一致します。

  NOT Status WITHIN 10 SECONDS

2.5.7 一致したパターンのイベント構造

パターンが一致した場合に生成されるイベントの構造は、MATCHING 句内にバインドされている変数の共用体の構造によって決定されます。このため、一致したイベントからデータを取得するには変数のバインドが存在している必要があります。

たとえば、次のパターンがあるとします。

  tick:=StockTick FOLLOWED BY news:=News(stockSymbol = tick.stockSymbol)

一致するイベントには、StockTick 型の tick プロパティおよび News 型の news プロパティという 2 つのプロパティを持つ複合イベント型が含まれています。

2.6 WHERE

WHERE 句は EPL 文の省略可能な句です。WHERE 句を使用してイベント ストリームを結合し、イベントをフィルタ処理できます。WHERE 句に集約関数を含めることはできません。集約関数を使用してフィルタ処理するには、HAVING 句を使用する必要があります。

  WHERE aggregate_free_expression

WHERE 句では、比較演算子 =, <, >, >=, <=, !=, <>, IS NULL, IS NOT NULL および ANDOR を使用した論理結合がサポートされています。以下にいくつかの例を示します。

  ...WHERE fraud.severity = 5 AND amount > 500
  ... WHERE (orderItem.orderId IS NULL) OR (orderItem.class != 10)
  ... WHERE (orderItem.orderId = NULL) OR (orderItem.class <> 10)
  ... WHERE itemCount / packageCount > 10

2.7 GROUP BY

GROUP BY 句は EPL 文で省略可能です。GROUP BY 句は EPL 文の結果をグループに分割します。1 つまたは複数のイベント プロパティ名、または式の計算結果によるグループ化が可能です。集約関数と共に使用した場合、GROUP BY では各サブグループで計算が取得されます。GROUP BY は集約関数なしに使用できますが、通常は混乱した結果が生成されます。

たとえば、次の文では、直前の 30 秒間のすべての StockTickEvents の銘柄ごとの合計価格が返されます。

  SELECT symbol, SUM(price) 
  FROM StockTickEvent RETAIN 30 SEC 
  GROUP BY symbol

GROUP BY 句の構文は以下のとおりです。

  GROUP BY arregate_free_expression [, arregate_free_expression] [, …]

EPL では、GROUP BY 句の式に以下の制限があります。

GROUP BY 句に複数の式をリストしてグループをネストできます。GROUP BY でセットが確立されると、集約関数が適用されます。この文では、直前の 30 秒間のすべての株価表示イベントの中央量が、銘柄および表示データ フィード別にグループ化されてポストされます。EPL により、各グループごとに 1 つのイベントが文の更新リスナにポストされます。

  SELECT symbol, tickDataFeed, MEDIAN(volume)
  FROM StockTickEvent RETAIN 30 SECONDS
  GROUP BY symbol, tickDataFeed

上の文では、SELECT リスト内のイベント プロパティ (symbol および tickDataFeed) が GROUP BY 句にもリストされています。このため、この文は、SELECT リスト内の非集約イベント プロパティが GROUP BY カラムに一致する必要があることを規定している SQL 標準に従っています。

EPL では、SELECT リスト内の 1 つまたは複数のイベント プロパティが GROUP BY 句にリストされていない文もサポートされています。下の文はこのようなケースを示しています。この文では、直前の 30 秒間の株価表示の標準偏差が計算され、銘柄別に集約され、各イベントごとに symboltickDataFeed、および price の標準偏差がポストされます。

  SELECT symbol, tickDataFeed, STDDEV(price)
  FROM StockTickEvent RETAIN 30 SECONDS
  GROUP BY symbol

上の例では、price イベント プロパティは依然として symbol に基づいて集約されますが、グループごとに 1 つのイベントではなく、着信イベントごとに 1 つのイベントが生成されます。

また、EPL では、GROUP BY 句の 1 つまたは複数のイベント プロパティが SELECT リストに含まれていない文がサポートされています。この例では、symbol および tickDataFeed ごとの平均偏差が計算され、グループごとに 1 つのイベントがポストされ、生成されたイベントには symbolprice の平均偏差が含まれています。ポストされた結果に tickDataFeed が含まれていないため、混乱が生じる可能性があります。

  SELECT symbol, AVEDEV(price)
  FROM StockTickEvent RETAIN 30 SECONDS
  GROUP BY symbol, tickDataFeed

GROUP BY リストには式も使用できます。

  SELECT symbol * price, count(*)
  FROM StockTickEvent RETAIN 30 SECONDS
  GROUP BY symbol * price

GROUP BY 式の結果が null 値の場合、null 値は固有のグループになります。すべての null 値が同じグループに集約されます。COUNT(expression) 集約関数では null 値が考慮されず、null 値のみが検出された場合、COUNT では 0 が返されます。

文では WHERE 句を GROUP BY と共に使用できます。WHERE 句の条件を満たしていないイベントはグループ化が実行される前に消去されます。たとえば、下の文では、量が 100 を超える直前の 30 秒間の株価表示数がポストされ、グループ (symbol) ごとに 1 つのイベントがポストされます。

  SELECT symbol, count(*)
  FROM StockTickEvent RETAIN 30 SECONDS
  WHERE volume > 100
  GROUP BY symbol

2.8 HAVING

HAVING 句は EPL 文で省略可能です。HAVING 句を使用して、GROUP BY 句で定義されたイベントを承認または拒否します。WHERESELECT 句の条件を設定するのと同様、HAVING 句は GROUP BY 句の条件を設定します。ただし、WHERE 句には集約関数を含めることができず、HAVING では多くの場合に集約関数が使用される点が異なります。

  HAVING expression

この文は、HAVING 句で集約関数を使用する例です。直前の 30 秒間の株価表示イベントで、合計価格が 1000 を超える銘柄についてのみ銘柄ごとの合計価格がポストされます。HAVING 句により合計価格が 1000 以下のすべての銘柄が消去されます。

  SELECT symbol, SUM(price)
  FROM StockTickEvent RETAIN 30 SEC
  GROUP BY symbol
  HAVING SUM(price) > 1000

HAVING 句に複数の条件を含めるには、ANDOR、または NOT を使用して条件を組み合わせます。これを示す下の文では、合計価格が 1000 を越え、平均量が 500 未満のグループのみが選択されます。

  SELECT symbol, SUM(price), AVG(volume)
  FROM StockTickEvent RETAIN 30 SEC
  GROUP BY symbol
  HAVING SUM(price) > 1000 AND AVG(volume) < 500

HAVING 句を使用する文では GROUP BY 句も使用する必要があります。GROUP BY を省略すると、WHERE 句で除外されないすべてのイベントが 1 つのグループとして返されます。この場合、HAVING には集約関数を含めることができる点を除いて、HAVINGWHERE と同様に動作します。

下の例が示すように、HAVING 句は GROUP BY 句なしでも使用できます。この例では、直前の 30 秒間のすべての株価表示イベントで価格が現在実行中の平均価格に満たないイベントがポストされます。

  SELECT symbol, price, AVG(price)
  FROM StockTickEvent RETAIN 30 SEC
  HAVING price < AVG(price)

2.8.1 MATCHING、WHERE および GROUP BY 句との対話

EPL 文にサブクエリ、MATCHING 句、WHERE 条件、GROUP BY 句、および HAVING 条件が含まれている場合、最終結果はそれぞれの句が実行される順序によって決定されます。

  1. 文に出現するサブクエリが最初に実行されます。サブクエリは、イベントが外部クエリの枠に入れられるためのフィルタとして動作します。

  2. MATCHING 句にイベント ストリームのフィルタ条件が存在する場合は、この条件により枠に入れられるイベントが指定されます。フィルタ条件を満たさないイベントはすべて破棄されます。

  3. WHERE 句により、検索条件に一致しないイベントが除外されます。

  4. SELECT リストの集約関数で各グループの概略値が計算されます。

  5. HAVING 句により、検索条件に一致しないイベントが最終結果から除外されます。

次のクエリでは、SELECT 句で集約関数を使用し、フィルタ、WHEREGROUP BY、および HAVING 句を 1 つの文で使用する場合を示しています。

  SELECT tickDataFeed, STDDEV(price)
  FROM (SELECT * FROM StockTickEvent WHERE symbol='ACME')
  RETAIN 10 EVENTS
  WHERE volume > 1000
  GROUP BY tickDataFeed
  HAVING STDDEV(price) > 0.8

EPL ではイベント ストリーム StockTickEvent に対するサブクエリを使用してイベントがフィルタされます。上の例では、直前の 10 件のイベントに対し銘柄 ACME のイベントのみが枠に入れられ、他のすべてのイベントは単に破棄されます。WHERE 句により、枠にポストされたイベントのうち、量が 1000 を超えるという条件に一致しないイベント (枠に入れられるイベントおよび枠を離れるイベント) が削除されます。GROUP BY 句に指定されているとおり、各表示データ フィードごとに、残りのイベントに STDDEV 標準偏差の集約関数が適用されます。各 tickDataFeed 値につき 1 つのイベントが生成されます。EPL では HAVING 句が適用され、price の標準偏差が 0.8 を超える tickDataFeed グループのイベントのみが承認されます。

2.9 ORDER BY

ORDER BY 句は EPL で省略可能です。これを使用して、プロパティまたはプロパティを使用する式で出力イベントを順序付けします。たとえば、次の文では 1 分間の株価表示イベントがバッチ処理され、最初に価格、次に量によって並べ替えられます。

  SELECT symbol 
  FROM StockTickEvent RETAIN BATCH OF 1 MINUTE
  ORDER BY price, volume

ORDER BY 句の構文は以下のとおりです。

  ORDER BY expression [ASC | DESC] [, expression [ASC | DESC] [,…]]

EPL では、ORDER BY 句の式に以下の制限があります。

他の点では、SELECT 句に使用できる任意の種類の式、および SELECT 句に定義されている任意のエリアスは、ORDER BY 句でも有効です。

2.10 OUTPUT

OUTPUT 句は EPL で省略可能です。この句を使用してイベント出力の割合を制御または安定化させます。たとえば、次の文では新しいイベントと古いイベントがバッチ処理され、これらが 90 秒間隔で出力されます。

  SELECT * 
  FROM StockTickEvent RETAIN 5 EVENTS 
  OUTPUT EVERY 90 SECONDS

出力の割合を制限する構文は以下のとおりです。

  OUTPUT [ALL | ( (FIRST | LAST) [number]] EVERY number [EVENTS | time_unit]

各項目は次のとおりです。

  time_unit: MIN | MINUTE | MINUTES | SEC | SECOND | SECONDS | MILLISECONDS | MS

ALL キーワードはデフォルトであり、バッチ内のすべてのイベントが出力されることを指定します。バッチ サイズは時間またはイベント数で指定できます。

FIRST キーワードは出力バッチ内の最初のイベントのみが出力されることを指定します。省略可能な数値修飾子を使用して複数のイベントを出力できます。FIRST キーワードでは、最初に一致したイベントが到着後すぐに出力されるようエンジンに指示され、その後は指定された時間間隔またはイベント数の一致するイベントは無視されます。時間間隔が経過するか、または一致するイベント数に到達した後は、同じサイクルが開始されます。

LAST キーワードは、指定の時間間隔内で最後のイベントのみを出力するか、または指定された数の一致するイベントが蓄積された後で最後のイベントのみを出力することを指定します。省略可能な数値修飾子を使用して複数のイベントを出力できます。

時間間隔は分またはミリ秒でも指定できます。次の文は最初の文と同じです。

  SELECT * 
  FROM StockTickEvent RETAIN 5 EVENTS 
  OUTPUT EVERY 1.5 MINUTES

出力を安定化する 2 つ目の方法は、特定の数のイベントが収集されるまでイベントをバッチ処理する方法です。次の文では、新しい 5 件 (またはそれ以上) あるいは古い 5 件 (またはそれ以上) のイベントがバッチ処理された後で初めて出力されます。

  SELECT * 
  FROM StockTickEvent RETAIN 30 SECONDS 
  OUTPUT EVERY 5 EVENTS

また、省略可能な LAST キーワードを使用してイベント出力をさらに変更できます。これにより、最後のイベント (複数可) の出力のみが出力バッチに到着します。下の例では、最後の 5 件のイベントが 3 分ごとに出力されます。

  SELECT * 
  FROM StockTickEvent RETAIN 30 SECONDS 
  OUTPUT LAST 5 EVERY 3 MINUTES

FIRST キーワードを使用すると間隔の開始時に通知を受け取ることができます。この例では、rate がしきい値を下回るたびに直ちに通知されます。

  SELECT * 
  FROM TickRate RETAIN 30 SECONDS
  WHERE rate < 100
  OUTPUT FIRST EVERY 60 SECONDS

2.10.1 GROUP BY および HAVING 句との対話

OUTPUT 句が GROUP BY および HAVING 句と対話する方法には 2 種類あります。まず、OUTPUT EVERY n EVENTS の場合、数字 n は GROUP BY 句に到着するイベントの数を指します。つまり、GROUP BY 句でグループにつき 1 つのイベントのみが出力される場合、または到着するイベントが HAVING 句の条件を満たしていない場合、実際に文で出力されるイベント数は n より少ない場合があります。

2 つ目に、LAST および ALL キーワードは、集約関数と GROUP BY 句が含まれている文で使用する場合に特別な意味を持ちます。LAST キーワードは、集約値が最新のイベント バッチで更新されているグループのみが出力されることを指定します。ALL キーワード (デフォルト) は、グループの集約値が更新されているかどうかに関係なく、これまでに見つかったすべてのグループの最新のデータが出力されることを指定します。

2.11 INSERT INTO

INSERT INTO 句は EPL で省略可能です。この句を指定して、文の結果を後続の文で使用できるイベント ストリームとして作成できます。また、この句を使用して、複数のイベント ストリームを結合して 1 つのイベント ストリームを作成できます。

  INSERT INTO CombinedEvent
  SELECT A.customerId AS custId, A.timestamp - B.timestamp AS latency
  FROM EventA A, EventB B RETAIN 30 MIN
  WHERE A.txnId = B.txnId

上の文の INSERT INTO 句ではタイプ CombinedEvent のイベントが生成されます。生成されたそれぞれの CombinedEvent イベントには、custId および latency という 2 つのイベント プロパティが含まれています。上の文で生成されたイベントを後続の文で使用できます。たとえば、下の文では生成されたイベントを使用しています。

  SELECT custId, SUM(latency)
  FROM CombinedEvent RETAIN 30 MIN
  GROUP BY custId

INSERT INTO 句にはイベント タイプ エリアスのみを含めるか、またはイベント タイプ エリアスおよび 1 つまたは複数のイベント プロパティ名を含めることができます。INSERT INTO 句の構文は以下のとおりです。

  INSERT [ISTREAM | RSTREAM] INTO event_type_alias [(prop_name [,prop_name, [,…]] ) ]

ISTREAM (デフォルト) および RSTREAM キーワードは省略可能です。いずれのキーワードも指定しない場合、エンジンでは文で生成された挿入ストリーム イベントがアタッチされた更新リスナに提供されます。挿入ストリームはそれぞれの枠またはストリームに入れられるイベントで構成されます。RSTREAM キーワードを指定した場合、エンジンでは文で生成された削除ストリーム イベントが提供されます。削除ストリームはそれぞれの枠を離れるイベントで構成されます。

event_type_alias はエンジンで生成されたイベントを指定する識別子です。文中では識別子を使用して、指定の名前のイベントをフィルタおよび処理できます。

また、エンジンでは、INSERT INTO 句が含まれている文に更新リスナがアタッチされることが許可されます。

イベント ストリームを結合するには、結合する任意の EPL 文で同じ event_type_alias 識別子を使用するだけで済みます。使用するイベント プロパティの数と名前が同じであり、イベント プロパティのタイプが一致することを確認します。

EPL では、INSERT INTO 句に以下の制限があります。

下の例では、使用するプロパティ名が明示的に定義されたもう 1 つの形式の INSERT INTO 句を示します。

  INSERT INTO CombinedEvent (custId, latency)
  SELECT A.customerId, A.timestamp - B.timestamp
  FROM EventA A, EventB B RETAIN 30 MIN
  WHERE A.txnId = B.txnId

RSTREAM キーワードを使用して、削除ストリーム イベントのみを生成するようエンジンに指示します。これは、イベントが枠に入れられたときでなく枠を離れたときにアクションを起動する必要がある場合に便利です。下の文では、EventAEventB が 30 分後に枠を離れたときに CombinedEvent イベントが生成されます。

  INSERT RSTREAM INTO CombinedEvent
  SELECT A.customerId AS custId, A.timestamp - B.timestamp AS latency
  FROM EventA A, EventB B RETAIN 30 MIN
  WHERE A.txnId = B.txnId

2.12 単純サブクエリと相関サブクエリ

サブクエリは別の文の内部にある SELECT です。EPL では、EPL 文の SELECT 句および WHERE 句内のサブクエリがサポートされています。サブクエリでは、複雑な結合を必要とするような操作を実行するためのもう 1 つの手段が提供されます。また、サブクエリでは複雑な結合よりも文が読みやすくなります。

EPL では、単純サブクエリと相関サブクエリの両方がサポートされています。単純なサブクエリでは、内部クエリが外部クエリの要素 (行) を参照しません。次の例は、SELECT 句内の単純なサブクエリを示します。

  SELECT assetId, 
    (SELECT zone 
     FROM ZoneClosed.std:lastevent) AS lastClosed  
  FROM RFIDEvent
  SELECT assetId, 
    (SELECT zone 
     FROM ZoneClosed RETAIN ALL EVENTS) AS lastClosed  
  FROM RFIDEvent

次の例に示すように、外部クエリに依存している内部クエリは相関クエリと呼ばれます。クエリでは、内部クエリ内の WHERE 句が外部クエリからのストリームを使用しています。

  SELECT * 
  FROM RfidEvent AS RFID 
  WHERE 'Dock 1' =
    (SELECT name 
     FROM Zones RETAIN ALL EVENTS WITH UNIQUE  zoneId 
      WHERE zoneId = RFID.zoneId)

上記の例は WHERE 句内のサブクエリを示します。文では、ゾーン ID に基づいて文字列定数とゾーン名が一致する RFID イベントが選択されます。文では RETAIN 句に WITH UNIQUE サブ句を使用することで、ゾーン ID ごとの最後のイベントのみがサブクエリによる処理で保持されることが保証されます。

次の例は SELECT 句内の相関サブクエリです。このクエリの SELECT 句では、ゾーン ID で関連付けられた Zones イベント セットに対するサブクエリによってゾーン名が取得されます。

  SELECT zoneId, 
    (SELECT name 
     FROM Zones RETAIN ALL EVENTS WITH UNIQUE zoneId
     WHERE zoneId = RFID.zoneId) AS name 
  FROM RFIDEvent

単純サブクエリまたは相関サブクエリで複数の行が返される場合、Oracle CEP ではサブクエリの結果として null 値が返されます。サブクエリで返されるイベント数を制限するには、RETAIN 句で WITH UNIQUE または PARTITION BY を使用することを検討します。

サブクエリの SELECT 句ではワイルドカードによる選択も可能であり、FROM 句で定義されているイベント タイプの基になるイベント オブジェクトがイベント プロパティとして返されます。例を示します。

  SELECT 
    (SELECT * 
     FROM MarketData RETAIN 1 EVENT) AS md
  MATCHING WITHIN 10 SECONDS

上記の文の出力イベントには、基になる MarketData イベントが md というプロパティに含まれています。文では、パターン定義に従って、10 秒ごとに最後の MarketData イベントが md というプロパティに挿入されるか、または MarketData イベントがそれまで検出されなかった場合は null 値が挿入されます。

サブクエリに適用される制限は以下のとおりです。

1 つまたは複数のサブクエリが含まれている文のパフォーマンスは、主に 2 つの要因に応じて変化します。1 つ目には、サブクエリによって、サブクエリ ストリーム内の 1 つまたは複数のカラムがイコール記号 (=) を使用して外側の文のストリームと関連付けられている場合、Oracle CEP では行の迅速な取得のために、関連付けられた (結合された) キー値に基づいて適切なインデックスが自動的に構築されます。2 つ目の要因には、サブクエリ ストリーム内の行数とフィルタ条件 (WHERE 句) の複雑さがあります。これは、サブクエリ ストリーム内の各行が WHERE 句のフィルタに対して評価される必要があるためです。

2.13 パラメータ化されたクエリ

パラメータ化されたクエリを使用すると、EPL クエリの内部に疑問符の形式でプレースホルダを含めることができます。プレースホルダは実行時に値とバインドされ、通常の文にコンパイルされます。プロセスは JDBC の PreparedStatement とほぼ同じです。

パラメータ化されたクエリを使用すると、考えられるパラメータ値のそれぞれに個別のルールを作成する必要がなくなります。たとえば、シグナル トレーディング アプリケーションには照合の対象となる銘柄記号を選択する値のみが異なる 300 のルールが含まれています。実世界のアプリケーションでは、ルールのロジックが変更されるとそれによって 300 のルールすべてに同一の変更を加える必要が生じるため、300 の個別のルールを管理することは厄介な作業です。代わりに、パラメータ化されたクエリの手法によって、開発者は後から特定の銘柄記号の値にバインドされるプレースホルダをクエリに配置できます。パラメータ化されたクエリは、値とバインドされた後は通常のクエリにコンパイルされるため、クエリのパフォーマンスに悪影響を及ぼすことはありません。

パラメータ化された EPL クエリに関連付けられたパラメータを Java コードを作成せずに実行時に変更するには、『Oracle CEP 管理者ガイド』の「wlevs.Admin コマンドライン インタフェース」を使用します。

2.13.1 一般的な使用法

パラメータ化された EPL クエリでは疑問符を使用してプレースホルダの場所を指定します。現在定数を使用できる任意の式でプレースホルダを使用できます。定数を使用するのと同じ場所にプレースホルダを配置します。これは実際には、クエリの SELECT および WHERE 句にのみプレースホルダを指定できることを意味しています。RETAIN 句でプレースホルダを使用することはできません。

次の例は、パラメータ化されたクエリを示します。

  SELECT symbol, AVG(price) AS average, ? AS market
  FROM StockTick t RETAIN ALL EVENTS
  WHERE symbol = ?

この例では、SELECT および WHERE 句の両方でプレースホルダを指定する方法を示しています。実行時に、2 つのプレースホルダは NASDAQORCL などの値にバインドされるため、実行される実際の EPL 文は以下のようになります。

  SELECT symbol, AVG(price) AS average, NASDAQ AS market
  FROM StockTick t RETAIN ALL EVENTS
  WHERE symbol = ORCL

2.13.2 プロセッサ コンフィグレーション ファイルでのパラメータ化された EPL 文の使用

特定のプロセッサの EPL ルールをコンポーネント コンフィグレーション ファイルでコンフィグレーションした場合は、<rule> 要素を使用して EPL 文を通常どおり指定します。節 2.13.1「一般的な使用法」で説明しているように、疑問符を使用してプレースホルダを指定します。

次に、<binding> 要素を使用して、実行時にパラメータ化された EPL 文に渡す必要のあるカンマ区切りの値リストに対応する 1 つまたは複数の <params> 要素を指定します。各 <params> 要素によって、新しい EPL クエリが新しいパラメータを使用して効率的に実行されます。<binding>id 属性を使用して、バインドが適用される特定の EPL ルールを参照します。各 <params> 要素にはパラメータの単一のセットが含まれています。パラメータの順序はパラメータ化されたクエリに出現する疑問符の順序に対応しています。

<params>id 属性を使用して個別のパラメータ セットをユニークに識別します。これにより、後から JMX または wlevs.Admin を使用して単一のパラメータ セットを動的に削除できます。

コンフィグレーション ファイルの EPL ルールのように、親要素 <bindings> を使用して <binding> 要素をグループにまとめます。

次の例では、節 2.13.1「一般的な使用法」で説明しているクエリについて、パラメータ化されたクエリと実行時パラメータを指定する方法を示します。

<n1:config xmlns:n1="http://www.bea.com/ns/wlevs/config/application" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <processor>
        <name>myProcessor</name>
        <rules>
            <rule id="MarketRule"><![CDATA[ 
                 SELECT symbol, AVG(price) AS average, ? AS market
                 FROM StockTick t RETAIN ALL EVENTS
                 WHERE symbol = ?
            ]]></rule>
        </rules>
        <bindings>
            <binding id="MarketRule">
                <params id="nasORCL">NASDAQ,ORCL</params>
                <params id="nyJPM">NYSE,JPM</params>
                <params id="nyWFC">NYSE,WFC</params>
            </binding>
        </bindings>
    </processor>
</n1:config>

上記の例では、MarketRule EPL クエリに 2 つのプレースホルダが含まれています。1 つは SELECT 句、もう 1 つは WHERE 句にあります。<binding id="MarketRule"> 要素は、実行時に MarketRule に渡されるパラメータ セットのリストを指定します。各パラメータ セットは単一の <params> 要素で指定されます。パラメータ化されたクエリには 2 つのプレースホルダが含まれているため、各 <params> 要素にはカンマ区切りの 2 つの値が指定されています。

実行時に、上記のパラメータ化されたクエリは以下の 3 つのクエリに効率的に分解されます。

  SELECT symbol, AVG(price) AS average, NASDAQ AS market
  FROM StockTick t RETAIN ALL EVENTS
  WHERE symbol = ORCL
  SELECT symbol, AVG(price) AS average, NYSE AS market
  FROM StockTick t RETAIN ALL EVENTS
  WHERE symbol = JPM
  SELECT symbol, AVG(price) AS average, NYSE AS market
  FROM StockTick t RETAIN ALL EVENTS
  WHERE symbol = WFC

2.13.3 プログラムでのプリペアド EPL ステートメントの使用

アプリケーションで Oracle CEP API を使用して EPL ルールを作成および実行し、パラメータ化されたルールを使用する場合は、com.bea.wlevs.ede.api.PreparedStatement インタフェースを使用して、提供されたパラメータ値に基づいたインタフェースを持つ com.bea.wlevs.ede.api.BoundStatement のインスタンスを作成します。

PreparedStatement および BoundStatement は両方とも、コンパイルされた EPL クエリを表す基本オブジェクトである Statement を拡張します。PreparedStatement には、パラメータをクエリ内のプレースホルダにバインドし、クエリ内のプレースホルダの数を返し、バインド ID に基づいて BoundStatement のインスタンスを返す追加のメソッドがあります。BoundStatement には、EPL クエリのバインドに使用されるパラメータ値を取得し、実際のパラメータ化されたクエリ自体を取得する追加のメソッドがあります。

PreparedStatementstart() または stop() メソッドが呼び出されると、Oracle CEP では PreparedStatement から作成されたすべての BoundStatements が起動または停止されます。これは、パラメータ化されたクエリはそれ自身では実行不能であり、実際には固有のパラメータ値を使用して作成された BoundStatements のみが実行可能であるためです。

これらの API に関する完全なリファレンス マニュアルについては、『Oracle CEP Java API Reference』を参照してください。

次の Java の例は、節 2.13.1「一般的な使用法」で説明しているクエリを使用して BoundStatement を作成する方法を示します。

    String stmtString =
        "select symbol, avg(price) as average, ? as market " +
        "from StockTick t " +
        "retain all events " +
        "where symbol = ?"
        ;
    processorImpl.createStatement(stmtString);
    PreparedStatement preparedStmt = (PreparedStatement)processorImpl.createStatement(stmtString);
    BoundStatement orclBoundStmt = preparedStmt.bind(new String[] {"NASDAQ","ORCL"});