Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Переключайте службы с помощью раскрывающегося списка Версия. Дополнительные сведения о навигации.
Область применения: ✅ Microsoft Fabric ✅ Azure Data Explorer ✅ Azure Monitor ✅ Microsoft Sentinel
Сканирует данные, сопоставляет их и создает последовательности на основе предикатов.
Соответствующие записи определяются в соответствии с предикатами, определенными в шагах оператора. Предикат может зависеть от состояния, созданного предыдущими шагами. Выходные данные для соответствующей записи определяются входной записью и назначениями, определенными в шагах оператора.
Syntax
T| scan [ with_match_id=MatchIdColumnName ] [ declare(ColumnDeclarations ] )with()
Синтаксис columnDeclarations
ColumnName:ColumnType[=DefaultValue ] [ ..., ]
Синтаксис StepDefinition
step
StepName [ output = all | last | none:] Условие [ =>Назначение= [, ... ];
Дополнительные сведения о соглашениях синтаксиса.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| T | string |
✔️ | Входной табличный источник. |
| MatchIdColumnName | string |
Имя столбца типа long , добавляемого к выходным данным в рамках выполнения сканирования. Указывает 0-й индекс соответствия для записи. |
|
| ColumnDeclarations | string |
Объявляет расширение для схемы T. Эти столбцы назначаются значениями в шагах. Если значение не назначено, возвращается значение DefaultValue . Если иное не указано, значение DefaultValue не задано null. |
|
| StepName | string |
✔️ | Используется для ссылки на значения в состоянии сканирования условий и назначений. Имя шага должно быть уникальным. |
| Condition | string |
✔️ | Выражение, которое оценивается true или false определяет, какие записи из входных данных соответствуют шагу. Запись соответствует шагу, когда условие находится true в состоянии шага или с состоянием предыдущего шага. |
| Assignment | string |
Скалярное выражение, назначенное соответствующему столбцу, когда запись соответствует шагу. | |
output |
string |
Управляет логикой вывода шага на повторяющихся совпадениях.
all Выводит все записи, соответствующие шагу, last выводит только последнюю запись в серии повторяющихся совпадений для шага и none не выводит записи, соответствующие шагу. Значение по умолчанию — all. |
Returns
Запись для каждого совпадения записи из входных данных на шаг. Схема выходных данных — это схема источника, расширенная с столбцом в предложении declare .
Логика сканирования
scan передает сериализованные входные данные, запись по записи, сравнивая каждую запись с условием каждого шага при учете текущего состояния каждого шага.
State
Базовое состояние scan оператора можно рассматривать как таблицу с строкой для каждого.step Каждый шаг сохраняет собственное состояние с последними значениями столбцов и объявленными переменными из всех предыдущих шагов и текущего шага. При необходимости он также содержит идентификатор соответствия для текущей последовательности.
Если оператор сканирования имеет n шагов с именем s_1, s_2, ..., s_n, то s_k шаг будет иметь записи k в своем состоянии, соответствующем s_1, s_2, ..., s_k.
Имя шага. Формат ColumnName используется для ссылки на значение в состоянии. Например, будет ссылаться на столбецs_2.col1, col1 принадлежащий шагу s_2 в состоянии s_k. Подробный пример см. в пошаговом руководстве по логике сканирования.
Состояние запускается пустым и обновляется всякий раз, когда сканированная входная запись соответствует шагу. Если состояние текущего шага не является непустым, шаг называется активным последовательность.
Логика сопоставления
Каждая входная запись вычисляется по всем шагам в обратном порядке от последнего шага до первого. При оценке записи на некоторых шагах s_k применяется следующая логика:
Проверка 1. Если состояние предыдущего шага (s_k-1) непустимо, а r соответствует условию s_k, то возникает совпадение. Совпадение приводит к следующим действиям:
- Состояние s_k очищается.
- Состояние s_k-1 способствует тому, чтобы стать состоянием s_k.
- Назначения s_k вычисляются и расширяются.
- Расширенный r добавляется в выходные данные и в состояние s_k.
Note
Если проверка 1 приводит к совпадению, проверка 2 игнорируется, и r переходит к оценке по s_k-1.
Проверка 2. Если состояние s_k имеет активную последовательность или s_k является первым шагом, а r соответствует условию s_k, то возникает совпадение. Совпадение приводит к следующим действиям:
- Назначения s_k вычисляются и расширяются.
- Значения, представляющие s_k в состоянии s_k , заменяются значениями расширенного r.
- Если s_k определен как
output=all, расширенный r добавляется в выходные данные. - Если s_k является первым шагом, начинается новая последовательность, а идентификатор соответствия увеличивается на
1. Это влияет только на выходные данные приwith_match_idиспользовании.
После завершения проверок s_kr переходит к оценке по s_k-1.
Подробный пример этой логики см. в пошаговом руководстве по логике сканирования.
Examples
В этом разделе показано, как использовать синтаксис для начала работы.
Примеры, приведенные в этой статье, используют общедоступные таблицы в кластере справки, например
StormEventsтаблицу в базе данных Samples .
В примерах этой статьи используются общедоступные таблицы, такие как
Weatherтаблица в коллекции примеров Weather Analytics. Возможно, потребуется изменить имя таблицы в примере запроса, чтобы она соответствовала таблице в рабочей области.
Совокупная сумма
Вычислите совокупную сумму для входного столбца. Результат этого примера эквивалентен использованию row_cumsum().
range x from 1 to 5 step 1
| scan declare (cumulative_x:long=0) with
(
step s1: true => cumulative_x = x + s1.cumulative_x;
)
Output
| x | cumulative_x |
|---|---|
| 1 | 1 |
| 2 | 3 |
| 3 | 6 |
| 4 | 10 |
| 5 | 15 |
Совокупная сумма для нескольких столбцов с условием сброса
Вычислите совокупную сумму для двух входных столбцов, сбросьте значение суммы до текущего значения записи, когда суммарная сумма достигла 10 или более.
range x from 1 to 5 step 1
| extend y = 2 * x
| scan declare (cumulative_x:long=0, cumulative_y:long=0) with
(
step s1: true => cumulative_x = iff(s1.cumulative_x >= 10, x, x + s1.cumulative_x),
cumulative_y = iff(s1.cumulative_y >= 10, y, y + s1.cumulative_y);
)
Output
| x | y | cumulative_x | cumulative_y |
|---|---|---|---|
| 1 | 2 | 1 | 2 |
| 2 | 4 | 3 | 6 |
| 3 | 6 | 6 | 12 |
| 4 | 8 | 10 | 8 |
| 5 | 10 | 5 | 18 |
Заливка столбца вперед
Заполните строковый столбец. Каждое пустое значение присваивается последнему видное значение nonempty.
let Events = datatable (Ts: timespan, Event: string) [
0m, "A",
1m, "",
2m, "B",
3m, "",
4m, "",
6m, "C",
8m, "",
11m, "D",
12m, ""
]
;
Events
| sort by Ts asc
| scan declare (Event_filled: string="") with
(
step s1: true => Event_filled = iff(isempty(Event), s1.Event_filled, Event);
)
Output
| Ts | Event | Event_filled |
|---|---|---|
| 00:00:00 | A | A |
| 00:01:00 | A | |
| 00:02:00 | B | B |
| 00:03:00 | B | |
| 00:04:00 | B | |
| 00:06:00 | C | C |
| 00:08:00 | C | |
| 00:11:00 | D | D |
| 00:12:00 | D |
Теги сеансов
Разделите входные данные на сеансы: сеанс заканчивается 30 минут после первого события сеанса, после которого начинается новый сеанс. Обратите внимание на использование флага with_match_id , которое назначает уникальное значение для каждого отдельного совпадения (сеанса) сканирования. Кроме того, обратите внимание на то, что в этом примере используется специальное использование двух шагов , inSessiontrue поэтому оно записывает и выводит все записи из входных данных при endSession записи записей, которые происходят более 30 млн из sessionStart значения текущего совпадения. Шаг endSession имеет значение, output=none что он не создает выходные записи. Этот endSession шаг используется для продвижения состояния текущего совпадения до inSessionendSession, что позволяет начать новый матч (сеанс), начиная с текущей записи.
let Events = datatable (Ts: timespan, Event: string) [
0m, "A",
1m, "A",
2m, "B",
3m, "D",
32m, "B",
36m, "C",
38m, "D",
41m, "E",
75m, "A"
]
;
Events
| sort by Ts asc
| scan with_match_id=session_id declare (sessionStart: timespan) with
(
step inSession: true => sessionStart = iff(isnull(inSession.sessionStart), Ts, inSession.sessionStart);
step endSession output=none: Ts - inSession.sessionStart > 30m;
)
Output
| Ts | Event | sessionStart | session_id |
|---|---|---|---|
| 00:00:00 | A | 00:00:00 | 0 |
| 00:01:00 | A | 00:00:00 | 0 |
| 00:02:00 | B | 00:00:00 | 0 |
| 00:03:00 | D | 00:00:00 | 0 |
| 00:32:00 | B | 00:32:00 | 1 |
| 00:36:00 | C | 00:32:00 | 1 |
| 00:38:00 | D | 00:32:00 | 1 |
| 00:41:00 | E | 00:32:00 | 1 |
| 01:15:00 | A | 01:15:00 | 2 |
Вычисление длины сеанса на пользователя
Вычислите время начала сеанса, время окончания и длительность сеанса каждого пользователя с помощью scan оператора. Сеанс определяется как период между именем входа пользователя и последующим выходом. Объединение и partitionscanoutput=none использование output=all этого шаблона гарантирует, что одна строка возвращается на сеанс (т. е. для каждой пары входа и выхода), а не для каждой строки на событие.
Логика работает следующими способами:
- На шаге s1. Запись метки времени входа с помощью шага сканирования
output=none - На шаге s2: создание строки только при обнаружении соответствующего выхода с помощью
output=all
let LogsEvents = datatable(Timestamp:datetime, userID:int, EventType:string)
[
datetime(2024-05-28 08:15:23), 1, "login",
datetime(2024-05-28 08:30:15), 2, "login",
datetime(2024-05-28 09:10:27), 3, "login",
datetime(2024-05-28 12:30:45), 1, "logout",
datetime(2024-05-28 11:45:32), 2, "logout",
datetime(2024-05-28 13:25:19), 3, "logout"
];
LogsEvents
| sort by userID, Timestamp
| partition hint.strategy=native by userID (
sort by Timestamp asc
| scan declare (start: datetime, end: datetime, sessionDuration: timespan) with (
step s1 output=none: EventType == "login" => start = Timestamp;
step s2 output=all: EventType == "logout" => start = s1.start, end = Timestamp, sessionDuration = Timestamp - s1.start;
)
)
| project start, end, userID, sessionDuration
Output
| userID | start | end | sessionDuration |
|---|---|---|---|
| 1 | 2024-05-28 08:15:23.0000 | 2024-05-28 12:30:45.0000 | 04:15:22 |
| 3 | 2024-05-28 09:10:27.0000 | 2024-05-28 13:25:19.0000 | 04:14:52 |
| 2 | 2024-05-28 08:30:15.0000 | 2024-05-28 11:45:32.0000 | 03:15:17 |
События между запуском и остановкой
Найдите все последовательности событий между событием Start и событием Stop , которое происходит в течение 5 минут. Назначьте идентификатор соответствия для каждой последовательности.
let Events = datatable (Ts: timespan, Event: string) [
0m, "A",
1m, "Start",
2m, "B",
3m, "D",
4m, "Stop",
6m, "C",
8m, "Start",
11m, "E",
12m, "Stop"
]
;
Events
| sort by Ts asc
| scan with_match_id=m_id with
(
step s1: Event == "Start";
step s2: Event != "Start" and Event != "Stop" and Ts - s1.Ts <= 5m;
step s3: Event == "Stop" and Ts - s1.Ts <= 5m;
)
Output
| Ts | Event | m_id |
|---|---|---|
| 00:01:00 | Start | 0 |
| 00:02:00 | B | 0 |
| 00:03:00 | D | 0 |
| 00:04:00 | Stop | 0 |
| 00:08:00 | Start | 1 |
| 00:11:00 | E | 1 |
| 00:12:00 | Stop | 1 |
Вычисление настраиваемой воронки событий
Вычислите завершение воронки последовательности Hail —>Tornado>Thunderstorm Wind с State пользовательскими порогами времени между событиями (Tornadoвнутри 1h и Thunderstorm Wind внутри).2h Этот пример похож на подключаемый модуль funnel_sequence_completion, но обеспечивает большую гибкость.
StormEvents
| partition hint.strategy=native by State
(
sort by StartTime asc
| scan with
(
step hail: EventType == "Hail";
step tornado: EventType == "Tornado" and StartTime - hail.StartTime <= 1h;
step thunderstormWind: EventType == "Thunderstorm Wind" and StartTime - tornado.StartTime <= 2h;
)
)
| summarize dcount(State) by EventType
Output
| EventType | dcount_State |
|---|---|
| Hail | 50 |
| Tornado | 34 |
| Ураганный ветер | 32 |
Пошаговое руководство по проверке логики
В этом разделе демонстрируется логика сканирования с помощью пошагового руководства по событиям между запуском и остановкой .
let Events = datatable (Ts: timespan, Event: string) [
0m, "A",
1m, "Start",
2m, "B",
3m, "D",
4m, "Stop",
6m, "C",
8m, "Start",
11m, "E",
12m, "Stop"
]
;
Events
| sort by Ts asc
| scan with_match_id=m_id with
(
step s1: Event == "Start";
step s2: Event != "Start" and Event != "Stop" and Ts - s1.Ts <= 5m;
step s3: Event == "Stop" and Ts - s1.Ts <= 5m;
)
Output
| Ts | Event | m_id |
|---|---|---|
| 00:01:00 | Start | 0 |
| 00:02:00 | B | 0 |
| 00:03:00 | D | 0 |
| 00:04:00 | Stop | 0 |
| 00:08:00 | Start | 1 |
| 00:11:00 | E | 1 |
| 00:12:00 | Stop | 1 |
Состояние
Подумайте о состоянии scan оператора в виде таблицы со строкой для каждого шага, в котором каждый шаг имеет собственное состояние. Это состояние содержит последние значения столбцов и объявленные переменные из всех предыдущих шагов и текущего шага. Дополнительные сведения см. в разделе "Состояние".
В этом примере состояние может быть представлено в следующей таблице:
| step | m_id | s1.Ts | s1.Event | s2.Ts | s2.Event | s3.Ts | s3.Event |
|---|---|---|---|---|---|---|---|
| s1 | X | X | X | X | |||
| s2 | X | X | |||||
| s3 |
Значение "X" указывает, что определенное поле не имеет значения для этого шага.
Логика сопоставления
Этот раздел следует логике сопоставления по каждой записи Events таблицы, объясняя преобразование состояния и выходных данных на каждом шаге.
Note
Входная запись вычисляется по шагам в обратном порядке с последнего шага (s3) до первого шага (s1).
Запись 1
| Ts | Event |
|---|---|
| 0m | "A" |
Запись оценки на каждом шаге:
-
s3: проверка 1 не передается, так как состояниеs2пусто, и проверка 2 не передается, так какs3отсутствует активная последовательность. -
s2: проверка 1 не передается, так как состояниеs1пусто, и проверка 2 не передается, так какs2отсутствует активная последовательность. -
s1: проверка 1 не имеет значения, потому что нет предыдущего шага. Проверка 2 не передается, так как запись не соответствует условиюEvent == "Start". Запись 1 удаляется без влияния на состояние или выходные данные.
State:
| step | m_id | s1.Ts | s1.Event | s2.Ts | s2.Event | s3.Ts | s3.Event |
|---|---|---|---|---|---|---|---|
| s1 | X | X | X | X | |||
| s2 | X | X | |||||
| s3 |
Запись 2
| Ts | Event |
|---|---|
| 1m | "Start" |
Запись оценки на каждом шаге:
-
s3: проверка 1 не передается, так как состояниеs2пусто, и проверка 2 не передается, так какs3отсутствует активная последовательность. -
s2: проверка 1 не передается, так как состояниеs1пусто, и проверка 2 не передается, так какs2отсутствует активная последовательность. -
s1: проверка 1 не имеет значения, потому что нет предыдущего шага. Проверка 2 передается, так как запись соответствует условиюEvent == "Start". Это совпадение инициирует новую последовательность иm_idназначается. Запись 2 и ееm_id(0) добавляются в состояние и выходные данные.
State:
| step | m_id | s1.Ts | s1.Event | s2.Ts | s2.Event | s3.Ts | s3.Event |
|---|---|---|---|---|---|---|---|
| s1 | 0 | 00:01:00 | "Start" | X | X | X | X |
| s2 | X | X | |||||
| s3 |
Запись 3
| Ts | Event |
|---|---|
| 2m | "B" |
Запись оценки на каждом шаге:
-
s3: проверка 1 не передается, так как состояниеs2пусто, и проверка 2 не передается, так какs3отсутствует активная последовательность. -
s2: проверка 1 передается, так как состояниеs1неmpty и запись соответствует условиюTs - s1.Ts < 5m. Это совпадение приводит к очистке состоянияs1, а последовательностьs1должна быть повышена.s2Запись 3 и ееm_id(0) добавляются в состояние и выходные данные. -
s1: проверка 1 не имеет значения, так как предыдущий шаг отсутствует, и проверка 2 не передается, так как запись не соответствует условиюEvent == "Start".
State:
| step | m_id | s1.Ts | s1.Event | s2.Ts | s2.Event | s3.Ts | s3.Event |
|---|---|---|---|---|---|---|---|
| s1 | X | X | X | X | |||
| s2 | 0 | 00:01:00 | "Start" | 00:02:00 | "B" | X | X |
| s3 |
Запись 4
| Ts | Event |
|---|---|
| 3m | "D" |
Запись оценки на каждом шаге:
-
s3: проверка 1 не передается, так как запись не соответствует условиюEvent == "Stop", и проверка 2 не передается, так какs3отсутствует активная последовательность. -
s2: проверка 1 не передается, так как состояниеs1пусто. Она проходит проверку 2 , так как она соответствует условиюTs - s1.Ts < 5m. Запись 4 и ееm_id(0) добавляются в состояние и выходные данные. Значения из этой записи перезаписывают предыдущие значения состояния дляs2.Tsиs2.Event. -
s1: проверка 1 не имеет значения, так как предыдущий шаг отсутствует, и проверка 2 не передается, так как запись не соответствует условиюEvent == "Start".
State:
| step | m_id | s1.Ts | s1.Event | s2.Ts | s2.Event | s3.Ts | s3.Event |
|---|---|---|---|---|---|---|---|
| s1 | X | X | X | X | |||
| s2 | 0 | 00:01:00 | "Start" | 00:03:00 | "D" | X | X |
| s3 |
Запись 5
| Ts | Event |
|---|---|
| 4m | "Stop" |
Запись оценки на каждом шаге:
-
s3: проверка 1 передается, так какs2не является немплетной, и она соответствует условиюs3Event == "Stop". Это совпадение приводит к очистке состоянияs2, а последовательностьs2должна быть повышена.s3Запись 5 и ееm_id(0) добавляются в состояние и выходные данные. -
s2: проверка 1 не передается, так как состояниеs1пусто, и проверка 2 не передается, так какs2отсутствует активная последовательность. -
s1: проверка 1 не имеет значения, потому что нет предыдущего шага. Проверка 2 не передается, так как запись не соответствует условиюEvent == "Start".
State:
| step | m_id | s1.Ts | s1.Event | s2.Ts | s2.Event | s3.Ts | s3.Event |
|---|---|---|---|---|---|---|---|
| s1 | X | X | X | X | |||
| s2 | X | X | |||||
| s3 | 0 | 00:01:00 | "Start" | 00:03:00 | "D" | 00:04:00 | "Stop" |
Запись 6
| Ts | Event |
|---|---|
| 6m | "C" |
Запись оценки на каждом шаге:
-
s3: проверка 1 не передается, так как состояниеs2пусто, и проверка 2 не передается, так какs3не соответствует условиюs3Event == "Stop". -
s2: проверка 1 не передается, так как состояниеs1пусто, и проверка 2 не передается, так какs2отсутствует активная последовательность. -
s1: проверка 1 не передается, так как нет предыдущего шага, и проверка 2 не передается, так как она не соответствует условиюEvent == "Start". Запись 6 удаляется без влияния на состояние или выходные данные.
State:
| step | m_id | s1.Ts | s1.Event | s2.Ts | s2.Event | s3.Ts | s3.Event |
|---|---|---|---|---|---|---|---|
| s1 | X | X | X | X | |||
| s2 | X | X | |||||
| s3 | 0 | 00:01:00 | "Start" | 00:03:00 | "D" | 00:04:00 | "Stop" |
Запись 7
| Ts | Event |
|---|---|
| 8m | "Start" |
Запись оценки на каждом шаге:
-
s3: проверка 1 не передается, так как состояниеs2пусто, и проверка 2 не передается, так как она не соответствует условиюEvent == "Stop". -
s2: проверка 1 не передается, так как состояниеs1пусто, и проверка 2 не передается, так какs2отсутствует активная последовательность. -
s1: проверка 1 не пройдена, так как предыдущий шаг отсутствует. Она проходит проверку 2 , так как она соответствует условиюEvent == "Start". Это совпадение инициирует новую последовательность сs1новымm_id. Запись 7 и ееm_id(1) добавляются в состояние и выходные данные.
State:
| step | m_id | s1.Ts | s1.Event | s2.Ts | s2.Event | s3.Ts | s3.Event |
|---|---|---|---|---|---|---|---|
| s1 | 1 | 00:08:00 | "Start" | X | X | X | X |
| s2 | X | X | |||||
| s3 | 0 | 00:01:00 | "Start" | 00:03:00 | "D" | 00:04:00 | "Stop" |
Note
Теперь в состоянии есть две активные последовательности.
Запись 8
| Ts | Event |
|---|---|
| 11m | "E" |
Запись оценки на каждом шаге:
-
s3: проверка 1 не передается, так как состояниеs2пусто, и проверка 2 не передается, так как она не соответствуетs3условиюEvent == "Stop". -
s2: проверка 1 передается, так как состояниеs1неmpty и запись соответствует условиюTs - s1.Ts < 5m. Это совпадение приводит к очистке состоянияs1, а последовательностьs1должна быть повышена.s2Запись 8 и ееm_id(1) добавляются в состояние и выходные данные. -
s1: проверка 1 не имеет значения, так как предыдущий шаг отсутствует, и проверка 2 не передается, так как запись не соответствует условиюEvent == "Start".
State:
| step | m_id | s1.Ts | s1.Event | s2.Ts | s2.Event | s3.Ts | s3.Event |
|---|---|---|---|---|---|---|---|
| s1 | X | X | X | X | |||
| s2 | 1 | 00:08:00 | "Start" | 00:11:00 | "E" | X | X |
| s3 | 0 | 00:01:00 | "Start" | 00:03:00 | "D" | 00:04:00 | "Stop" |
Запись 9
| Ts | Event |
|---|---|
| 12m | "Stop" |
Запись оценки на каждом шаге:
-
s3: проверка 1 передается, так какs2не является немплетной, и она соответствует условиюs3Event == "Stop". Это совпадение приводит к очистке состоянияs2, а последовательностьs2должна быть повышена.s3Запись 9 и ееm_id(1) добавляются в состояние и выходные данные. -
s2: проверка 1 не передается, так как состояниеs1пусто, и проверка 2 не передается, так какs2отсутствует активная последовательность. -
s1: проверка 1 не передается, так как нет предыдущего шага, и проверка 2 не передается, так как запись не соответствует условию event == "Start".
State:
| step | m_id | s1.Ts | s1.Event | s2.Ts | s2.Event | s3.Ts | s3.Event |
|---|---|---|---|---|---|---|---|
| s1 | X | X | X | X | |||
| s2 | X | X | |||||
| s3 | 1 | 00:08:00 | "Start" | 00:11:00 | "E" | 00:12:00 | "Stop" |
Окончательные выходные данные
| Ts | Event | m_id |
|---|---|---|
| 00:01:00 | Start | 0 |
| 00:02:00 | B | 0 |
| 00:03:00 | D | 0 |
| 00:04:00 | Stop | 0 |
| 00:08:00 | Start | 1 |
| 00:11:00 | E | 1 |
| 00:12:00 | Stop | 1 |