メインコンテンツまでスキップ

EQL — イベントクエリ言語ガイド

目次


概要

主な使用位置 左側メニュー Automation > EQL クエリ(/query/index) で直接実行する他、高度な EQL アラーム · トリガー・ステートメント · フロー の条件式でも同じ文法を使用します。

EQL (Event Query Language) は PlantPulse Platform がリアルタイムストリーミングデータを SQL 文法のように問い合わせ、集計、パターンマッチングできるようにした独自のクエリ言語です。一般的な SQL が静的なテーブルを対象に動作するのに対し、EQL は継続的に流入するイベントストリームの上で動作し、毎時刻結果を emit します。

運用者は EQL 1 行で以下を実装できます。

  • リアルタイムモニタリング — タグ値が閾値超過した瞬間に即座に結果 emit
  • 資産単位の集計 — 毎 5分平均・最大・最小を自動計算
  • パターンマッチング — "A イベント後 30 秒以内に B イベントが来ない場合はアラーム"
  • 時系列結合 — 2 つのタグを時間順に比較

EQL は SQL とほぼ同じ文法を使用していますが、ウィンドウ (Window) という概念が追加されており、"直近 N 秒 / N 件" のような時間・長さの範囲を明示します。


EQL を使う場所

Platform 内での EQL 使用位置は以下の通りです。

EQL クエリ・トリガー・ステートメントは左側メニュー Automation セクションに並んでいます。 (CEP という名前のメニューはありません — 以前のドキュメントはこの 3 つを CEP の下位画面として記載していました。)

メニュー・画面内部 URL用途
Automation > EQL クエリドキュメント/query/index運用者が即席に EQL を実行して結果を確認 (探索・デバッグ)
Automation > トリガードキュメント/trigger/indexEQL マッチング結果を MQ トピックまたはストレージに自動パブリッシュ
Automation > ステートメントドキュメント/statement/index資産単位で登録されたルール (状態・集計・イベント・コマンド)
アラーム → EQL アラームEQL ルールで任意条件のアラーム発行
フロー → スクリプトflow_script_filter / flow_script_transform / flow_switch の EQL 式モード
タグフォーム — AI タブ予測・異常検知ルールの入力条件

EQL は読み取り専用です — データを変更しません。マッチング結果でアラーム発行やフローアクションノード呼び出しを行いたい場合は、CEP → トリガー または EQL アラーム で結果を接続してください。


基本文法

EQL の基本構造は SQL とほぼ同じです。

SELECT <column-or-function>
FROM <stream>.<window>
WHERE <condition>
GROUP BY <field>
HAVING <aggregation-condition>
ORDER BY <field> [ASC|DESC]

最もシンプルな EQL:

SELECT * FROM Point.win:time(1 sec)

直近1 秒間に到来したすべてのタグポイントを 1 秒ごとに emit。

ワイルドカードと列選択

構文意味
SELECT *すべての列を含む
SELECT tag_id, value特定列のみ
SELECT value AS v, tag_id AS idエイリアス (別名) の付与
SELECT value * 9 / 5 + 32 AS fahrenheit算術式の結果
SELECT CASE WHEN value > 80 THEN 'HIGH' ELSE 'OK' END AS level条件式

コメント

-- 한 줄 주석
/* 여러 줄
주석 */
SELECT * FROM Point.win:time(1 sec)

イベントストリーム (14種類 + 内部用 3種類)

EQL の FROM 節に記述できるストリーム (イベントソース) は以下の通りです。すべてのストリームは Platform が自動的に生成し、別途登録なしに即座に使用できます。

ここにない名前を FROM に書くと、ルールがデプロイされません。 登録されたイベントタイプのみ がストリームになります (plantpulse.core.engine.eql.EventTypes)。

タグドメイン (3種類)

ストリーム発生時点主要フィールド
Pointタグ値が受信されるたびtag_idvaluequalitytssite_idasset_idunitjava_type
PointMap同じですが tag('<id>') 関数と共に使用して複数タグをキー・バリュー形式で照会(PointMap 専用ヘルパー)
Alarmタグアラームが発生した時tag_idalarm_bandvaluethresholdpriorityband_message

資産ドメイン (6種類)

ストリーム発生時点主要フィールド
AssetData資産単位の時系列データ (集計結果)asset_idvalues(キー・バリュー)、ts
AssetEvent資産イベント発生 (開始・停止・保守など)asset_idevent_typedetailsts
AssetAlarm資産アラーム発生asset_idalarm_bandprioritymessage
AssetCommand資産にコマンド発行された時asset_idcommandargs
AssetAggregation1 分・5 分・1 時間の資産集計結果asset_idwindowagg_typevalues
AssetContext資産コンテキスト (メタ) の変更asset_idcontext_keybeforeafter
AssetHealthStatus · AssetConnectionStatus はストリームではありません

以前のドキュメントではこれら 2 つが資産ドメインストリームとして載っていましたが、登録されたイベントタイプではありません。 FROM AssetHealthStatus... と書くと、ルールはデプロイされません。

ヘルス・接続状態の評価はストリームではなく定期実行ジョブとして実行されます (AssetHealthStatusDeployer / AssetConnectionStatusDeployer)。その結果は画面と API で確認でき、EQL でステータス変化を捉えたい場合は、元となる AssetEvent · AssetAlarm または Point の未受信を not パターン で検知してください。

生産ドメイン (3種類)

ストリーム発生時点主要フィールド
Calendarシフト開始・終了・変更shift_idcalendar_ideventstart_timeend_time
WorkOrderワークオーダーのライフサイクル遷移order_idstatusprev_statusasset_idproduct_id
OEEOEE 評価結果の更新order_idasset_idoeeavailabilityperformancequality

システムドメイン (2種類)

ストリーム発生時点主要フィールド
Logシステム診断メッセージmodulelevelcodesummaryts
OSPerformanceサーバー OS リソース指標 (定期)CPU・メモリ・ディスクなど
Status ストリームはありません

Status という名前のイベントタイプは登録されていません。OPC・Edge の接続状態変化を EQL で捉えたい場合は、そのストリームは使用できません — Point の未受信を not パターン で検知する方法を使用してください。

内部用ストリーム (3種類)

登録されていますが、ルール作成用ではありません。診断・ヘルスチェックに使用されます。

ストリーム用途
DateTime定期的に発生する時刻イベント (時間ベースのルールのトリガー)
Pingエンジン生存確認
Testルール検証用

すべてのストリームは使用前に必ずウィンドウと結合する必要があります (Point.win:time(1 sec) のように)。ウィンドウなしで FROM Point のみ書くと、結果は即座に消えて表示されません。


ウィンドウ

ウィンドウは "ストリームから切り出した時間または長さの区間" です。EQL は 2 種類のウィンドウをサポートします。

時間ウィンドウ (Time Window)

文法意味
Point.win:time(1 sec)直近1 秒間に到来したすべてのイベント (スライディング)
Point.win:time(10 sec)直近 10 秒
Point.win:time(5 min)直近 5 分
Point.win:time(1 hour)直近 1 時間

サポートされる時間単位: sec(秒) · min(分) · hour(時間) · day(日)。

長さウィンドウ (Length Window)

文法意味
Point.win:length(100)直近100 件のイベント
Point.win:length(1000)直近 1,000 件

バッチウィンドウ (Batch Window)

win:time_batch / win:length_batch — ウィンドウが満杯になるか時間切れになったその瞬間に1 回だけ emit。リソース節減。

-- 매 1분마다 한 번씩 그 1분간 평균을 emit
SELECT avg(value) FROM Point.win:time_batch(1 min) WHERE tag_id = 'MOTOR-001.TEMP'

ウィンドウ選択ガイド

状況推奨ウィンドウ
リアルタイムモニタリング (値そのもの確認)win:time(1 sec)
短期平均・最大 (5 分平均など)win:time(5 min)
時間単位の集計win:time_batch(1 hour)
直近 N 件の比較win:length(N)
変化量の追跡win:length(2) + prev() 関数

WHERE 条件

SQL と同じ比較演算子を使用します。

演算子意味
= != <>tag_id = 'MOTOR-001'等しい・異なる
< <= > >=value > 80比較
BETWEENvalue BETWEEN 70 AND 90範囲
INtag_id IN ('A','B','C')リスト包含
LIKEtag_id LIKE 'MOTOR-%'パターンマッチング (% ワイルドカード)
IS NULL / IS NOT NULLquality IS NOT NULLnull の確認
AND OR NOTvalue > 80 AND quality = 'GOOD'論理結合

正規表現

SELECT * FROM Point.win:time(1 sec)
WHERE tag_id REGEXP '.*\\.TEMP$'

.TEMP で終わるすべてのタグのみマッチ。バックスラッシュは 2 回 (\\.) 入力します。

動的なサイト・資産フィルタ

SELECT * FROM Point.win:time(1 sec)
WHERE site_id = 'SITE-A'
AND asset_id LIKE 'LINE-1.%'
AND value > 75

集計関数

ウィンドウ内のイベントを集計します。

基本集計

関数意味
count(*)イベント件数SELECT count(*) FROM Point.win:time(10 sec)
sum(field)合計sum(value)
avg(field)平均avg(value)
min(field)最小値min(value)
max(field)最大値max(value)
median(field)中央値median(value)
stddev(field)標準偏差stddev(value)
variance(field)分散variance(value)
first(field)ウィンドウ開始値first(value)
last(field)ウィンドウ終了値last(value)

DISTINCT 集計

SELECT count(distinct tag_id) AS unique_tags
FROM Point.win:time(1 min)

CASE との組み合わせ

SELECT
count(CASE WHEN value > 80 THEN 1 END) AS high_count,
count(CASE WHEN value <= 80 THEN 1 END) AS ok_count
FROM Point.win:time(1 min)
WHERE tag_id = 'MOTOR-001.TEMP'

時系列関数

関数意味
prev(N, field)N ステップ前の値value - prev(1, value) (直前値との差分)
prevwindow(field)ウィンドウ内のすべての過去値配列prevwindow(value)
rate(field)単位時間当たりの変化率rate(value)

グループ化・ソート

GROUP BY

-- 자산별 최근 1분 평균 온도
SELECT asset_id, avg(value) AS avg_temp
FROM Point.win:time(1 min)
WHERE tag_id LIKE '%.TEMP'
GROUP BY asset_id

HAVING — 集計後フィルタ

-- 평균 > 80 인 자산만
SELECT asset_id, avg(value) AS avg_temp
FROM Point.win:time(1 min)
WHERE tag_id LIKE '%.TEMP'
GROUP BY asset_id
HAVING avg(value) > 80

ORDER BY · LIMIT

-- 가장 뜨거운 5개 자산
SELECT asset_id, max(value) AS peak
FROM Point.win:time(5 min)
WHERE tag_id LIKE '%.TEMP'
GROUP BY asset_id
ORDER BY peak DESC
LIMIT 5

LIMIT は結果 emit 時点の上位 N 件のみを含みます。


JOIN — ストリーム結合

2 つ以上のストリームを時間順に結合できます。

-- 같은 자산에서 같은 시간대의 온도와 압력을 한 행으로
SELECT p1.value AS temp, p2.value AS pressure, p1.asset_id
FROM Point.win:time(1 sec) AS p1,
Point.win:time(1 sec) AS p2
WHERE p1.tag_id LIKE '%.TEMP'
AND p2.tag_id LIKE '%.PRESSURE'
AND p1.asset_id = p2.asset_id

資産イベント + ワークオーダー結合

SELECT e.asset_id, e.event_type, w.order_id, w.status
FROM AssetEvent.win:time(5 min) AS e,
WorkOrder.win:time(5 min) AS w
WHERE e.asset_id = w.asset_id
AND e.event_type = 'STARTUP'
AND w.status = 'START'

2 つのストリームの時間ウィンドウが重なっている間のみ、結合結果が発生します。時間単位が異なるデータを比較する場合は win:time_batch で似た周期に合わせてください。


パターンマッチング

EQL の強力な機能 — "イベント A の後 N 秒以内に B が (来ない)" といったシーケンスを定義できます。

every — 毎回マッチング

SELECT * FROM pattern [
every a = AssetEvent(event_type = 'STARTUP')
-> b = AssetEvent(event_type = 'SHUTDOWN', asset_id = a.asset_id)
where timer:within(60 sec)
]

開始イベント → 60 秒以内に停止イベントのペアを毎回マッチング。短い稼動後に即座に停止する異常パターン検知。

not — N 時間の間に起きていない

SELECT * FROM pattern [
every a = AssetEvent(event_type = 'STARTUP')
-> ( timer:interval(30 min)
and not AssetData(asset_id = a.asset_id) )
]

開始後 30 分間データが到来しない場合、マッチング (応答のない資産検知)。

and / or — 同時またはいずれか一つ

SELECT * FROM pattern [
( every AssetAlarm(priority = 'ERROR') )
and
( every WorkOrder(status = 'START') )
]

パターンマッチングの主要キーワード

キーワード意味
every <e>e が発生するたび、マッチング
e1 -> e2e1 の後に e2 が発生 (順序マッチング)
e1 and e22 つのイベントがいずれも発生 (順序不問)
e1 or e2いずれか一つが発生
not ee が発生していない
timer:within(<duration>)指定時間内のみマッチング
timer:interval(<duration>)指定時間の間待機

時間・状態関数

時間関数

関数意味
current_timestamp現在時刻 (ms)
current_date()今日の日付 (yyyy-MM-dd)
timestamp(field)イベントの timestamp 抽出
hour_of_day(ts)0~23 時
day_of_week(ts)1(日)~7(土)
minute_of_hour(ts)0~59 分
dayofmonth(ts)1~31 日
-- 야간 (22시~6시) 발생 알람만
SELECT * FROM Alarm.win:time(1 hour)
WHERE hour_of_day(ts) >= 22 OR hour_of_day(ts) < 6

状態関数

関数意味
tag('<tag_id>')そのタグの最新値 (PointMap コンテキスト)
prev_status(asset_id)資産の直前状態
health(asset_id)資産ヘルス状態 (OK/WARN/ERROR/UNKNOWN)
is_in_shift(asset_id)資産がシフト内にあるか

算術・文字列関数

関数意味
abs(x) / round(x, n) / floor(x) / ceil(x)数学
pow(x, y)x の y 乗
sqrt(x)平方根
length(s)文字列長
upper(s) / lower(s)大小文字変換
substring(s, start, len)部分文字列
concat(a, b, ...)連結

変数とコンテキスト

変数 — 動的閾値

-- 변수 정의 (운영자가 화면에서 조정 가능)
create variable double max_temp = 80;

-- 변수 사용
SELECT * FROM Point.win:time(1 sec)
WHERE tag_id LIKE '%.TEMP' AND value > max_temp

変数値は運用中に変更でき、すべての EQL ルールが即座に新しい値を使用します。

コンテキスト — 時間・条件ベースの有効化

Platform にはよく使うコンテキストが事前定義されており、そのまま利用できます。

コンテキスト有効条件
EVERY_1_MINUTES毎 1 分
EVERY_5_MINUTES毎 5 分
EVERY_10_MINUTES毎 10 分
EVERY_30_MINUTES毎 30 分
EVERY_1_HOURS毎 1 時間
EVERY_3_HOURS毎 3 時間
EVERY_6_HOURS毎 6 時間
EVERY_12_HOURS毎 12 時間
DAY_WORK_TIME平日 09:00~18:00
-- 5분마다 한 번씩 평균 온도 emit (그 사이에는 결과가 안 옴)
context EVERY_5_MINUTES
SELECT avg(value) AS avg_temp
FROM Point.win:time(5 min)
WHERE tag_id = 'MOTOR-001.TEMP'
-- 주간 근무시간에만 평가
context DAY_WORK_TIME
SELECT * FROM AssetAlarm.win:time(1 sec)
WHERE priority = 'ERROR'

実践例 12 選

例 1 — リアルタイムで 1 つのタグをモニタリング

SELECT value, ts, quality
FROM Point.win:time(1 sec)
WHERE tag_id = 'MOTOR-001.SPEED'

例 2 — 閾値超過を即座に検知

SELECT tag_id, value, ts
FROM Point.win:time(1 sec)
WHERE tag_id LIKE '%.TEMP' AND value > 90

例 3 — 資産別 5 分平均 (5 分ごとに emit)

context EVERY_5_MINUTES
SELECT asset_id, avg(value) AS avg_temp, max(value) AS peak
FROM Point.win:time(5 min)
WHERE tag_id LIKE '%.TEMP'
GROUP BY asset_id

例 4 — 変化量 (直前値比較)

SELECT tag_id, value, value - prev(1, value) AS delta
FROM Point.win:length(2)
WHERE tag_id = 'TANK-001.LEVEL'

例 5 — 夜勤シフトの ERROR アラームのみ

SELECT tag_id, priority, band_message, ts
FROM Alarm.win:time(1 sec)
WHERE priority = 'ERROR'
AND hour_of_day(ts) >= 22 OR hour_of_day(ts) < 6

例 6 — 資産ヘルス遷移 (OK → WARN)

SELECT asset_id, status, prev_status, ts
FROM AssetHealthStatus.win:time(1 sec)
WHERE prev_status = 'OK' AND status = 'WARN'

例 7 — ワークオーダー OEE 低下

SELECT order_id, asset_id, oee, availability, performance, quality
FROM OEE.win:time(1 sec)
WHERE oee < 0.6

例 8 — 30 分応答のない資産検知

SELECT * FROM pattern [
every a = AssetData()
-> ( timer:interval(30 min)
and not AssetData(asset_id = a.asset_id) )
]

例 9 — 開始直後に停止 (不安定稼動)

SELECT * FROM pattern [
every a = AssetEvent(event_type = 'STARTUP')
-> b = AssetEvent(event_type = 'SHUTDOWN', asset_id = a.asset_id)
where timer:within(60 sec)
]

例 10 — 複数タグ同時比較 (PointMap)

SELECT
tag('MOTOR-001.TEMP') AS temp,
tag('MOTOR-001.PRESSURE') AS pressure,
tag('MOTOR-001.VIBRATION') AS vibration
FROM PointMap.win:time(1 sec)

例 11 — ライン単位の時間当たり累積生産量

context EVERY_1_HOURS
SELECT asset_id, sum(value) AS hourly_count
FROM AssetAggregation.win:time(1 hour)
WHERE agg_type = 'PRODUCED' AND asset_id LIKE 'LINE-%'
GROUP BY asset_id

例 12 — TOP 10 アラーム発生資産

context EVERY_10_MINUTES
SELECT asset_id, count(*) AS alarm_count
FROM AssetAlarm.win:time(10 min)
GROUP BY asset_id
ORDER BY alarm_count DESC
LIMIT 10

パフォーマンスガイド

1. ウィンドウサイズを意図的に小さく

-- ❌ 나쁜 예 — 24시간을 메모리에 유지
SELECT avg(value) FROM Point.win:time(24 hour)

-- ✅ 좋은 예 — 1시간만 메모리에 유지 + context 로 emit 주기 분리
context EVERY_1_HOURS
SELECT avg(value) FROM Point.win:time(1 hour)

2. WHERE 句をトリガーの近くに

タグ ID・資産 ID・サイト ID など静的フィルタは WHERE 句の最前に配置してください。後続の GROUP BY・HAVING より前に評価されます。

3. LIKE '%...%' の両側ワイルドカードは負荷が大きい

-- ❌ 나쁜 예
WHERE tag_id LIKE '%TEMP%'

-- ✅ 좋은 예
WHERE tag_id LIKE '%.TEMP' -- 접미사 매칭만

4. パターンマッチングは短いウィンドウと共に

pattern [ ... timer:within(<n-minutes>) ] の時間制限子を忘れずに。無制限パターンはメモリを継続的に占有します。

5. 結果 emit 頻度の調整

context EVERY_N_MINUTES コンテキストで EQL 自体の評価は 1 秒単位で行いますが、emit のみ N 分ごとに分離すると、ダウンストリーム負荷が軽減されます。


よくある質問

Q. EQL クエリを入力しましたが、結果画面に何も表示されません。 A. 以下をご確認ください。① FROM Point のみを書いていないか — ウィンドウが必要 (Point.win:time(1 sec))。② WHERE 条件が狭すぎてマッチングしていないのではないか。③ 右上の ▶ 開始ボタンを押したか。④ 結果パネルが ⏸ 停止状態ではないか。

Q. SQL との違いは何ですか? A. 最大の違いはウィンドウという概念です。EQL は無限ストリーム上で動作するため、"どの範囲" を指定する必要があります。その他 pattern [ ... ] シーケンスマッチングと context 時間コンテキストは SQL にはない機能です。

Q. win:time(1 sec)win:time_batch(1 sec) の違いは? A. win:time(1 sec)スライディング — イベントが到来するたびに結果を更新。win:time_batch(1 sec)タンブリング — 1 秒単位でまとめ、1 秒の終了時刻に1 回だけ emit。正確に 1 秒ごとの結果が必要な場合は batch を使用してください。

Q. pattern [ ... ] と通常の SELECT ... WHERE ... の違いは? A. SELECT は 1 つのイベント (またはウィンドウ) を見て評価しますが、patternイベントシーケンス (A の後 B、B なしで C など) を評価します。時間順序・因果関係が重要な場合は pattern を使用してください。

Q. 登録した変数は即座に反映されますか? A. はい。create variable で定義した変数値を画面で変更すると、既にデプロイされているすべての EQL ルールが次の評価から新しい値を使用します。

Q. EQL マッチング結果をアラームとして送信するには? A. CEP → トリガー に EQL を登録し、"MQ ストリーミング" または "ストレージ保存" オプションを有効化するか、アラーム → EQL アラーム に EQL を登録すると、マッチング時に自動的にアラームが発行されます。

Q. 資産単位ルールをすべての資産に一括適用できますか? A. CEP → ステートメント で資産単位 EQL ルールを定義し、モデル・オントロジーでそのルールを資産カテゴリにマッピングすると、同じカテゴリのすべての資産に自動デプロイされます。資産が追加されるたびに自動適用されます。

Q. EQL 1 行で 2 つのストリームを同時に扱えますか? A. はい。上記の JOIN セクションの例のように、2 つのストリームを FROM 句にカンマで列挙し、WHERE で結合条件を記述すれば可能です。

Q. 結果が多すぎます。 A. LIMIT N で上位 N 件のみ受け取るか、context EVERY_N_MINUTES で emit 周期を延長するか、win:time_batch を使用してバッチウィンドウでまとめてください。WHERE 句をより厳格にすることも効果的です。

Q. EQL 作成をどこで練習できますか? A. CEP → クエリ 画面が EQL 実習ツールです。1 行を入力して ▶ 実行すると、即座に結果が得られます。上記の 実践例 12 選 からコピーしてお試しください。


関連画面