Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Applies to: ✅Microsoft Fabric✅Azure Data Explorer✅Azure Monitor✅Microsoft Sentinel
Analisa dados, faz correspondências e cria sequências com base nos predicados.
Os registros correspondentes são determinados de acordo com predicados definidos nas etapas do operador. Um predicado pode depender do estado gerado pelas etapas anteriores. A saída para o registro correspondente é determinada pelo registro de entrada e atribuições definidas nas etapas do operador.
Syntax
T| scan [ with_match_id=MatchIdColumnName ] [ declare(ColumnDeclarations) ] with(StepDefinitions)
ColumnDeclarations syntax
ColumnName:ColumnType[=DefaultValue ] [, ... ]
StepDefinition syntax
step
StepName [ output = all | last | none] :Condition [ =>Column=Assignment [, ... ] ] ;
Learn more about syntax conventions.
Parameters
| Name | Tipo | Required | Description |
|---|---|---|---|
| T | string |
✔️ | A fonte tabular de entrada. |
| MatchIdColumnName | string |
O nome de uma coluna do tipo long que é anexada à saída como parte da execução da verificação. Indica o índice baseado em 0 da correspondência para o registro. |
|
| ColumnDeclarations | string |
Declares an extension to the schema of T. These columns are assigned values in the steps. If not assigned, the DefaultValue is returned. Unless otherwise specified, DefaultValue is null. |
|
| StepName | string |
✔️ | Usado para referenciar valores no estado de verificação de condições e atribuições. O nome da etapa deve ser exclusivo. |
| Condition | string |
✔️ | Uma expressão avaliada como true ou false que define quais registros da entrada correspondem à etapa. Um registro corresponde à etapa quando a condição é true com o estado da etapa ou com o estado da etapa anterior. |
| Assignment | string |
Uma expressão escalar que é atribuída à coluna correspondente quando um registro corresponde a uma etapa. | |
output |
string |
Controla a lógica de saída da etapa em correspondências repetidas.
all produz todos os registros correspondentes à etapa, last produz apenas o último registro de uma série de correspondências repetidas para a etapa e none não produz registros correspondentes à etapa. O padrão é all. |
Returns
Um registro para cada partida de um registro da entrada para uma etapa. O esquema da saída é o esquema da fonte estendida com a coluna na cláusula declare.
Scan logic
scan analisa os dados de entrada serializados, registro por registro, comparando cada registro com a condição de cada etapa, levando em consideração o estado atual de cada etapa.
State
O estado subjacente do operador scan pode ser considerado como uma tabela com uma linha para cada step. Cada etapa mantém seu próprio estado com os valores mais recentes das colunas e variáveis declaradas de todas as etapas anteriores e da etapa atual. Se relevante, ele também mantém o ID de correspondência para a sequência em andamento.
If a scan operator has n steps named s_1, s_2, ..., s_n then step s_k would have k records in its state corresponding to s_1, s_2, ..., s_k. The StepName.ColumnName format is used to reference a value in the state. For instance, s_2.col1 would reference column col1 that belongs to step s_2 in the state of s_k. Para obter um exemplo detalhado, consulte o passo a passo da lógica de verificação .
O estado começa vazio e é atualizado sempre que um registro de entrada digitalizado corresponde a uma etapa. When the state of the current step is nonempty, the step is referred to as having an active sequence.
Matching logic
Cada registro de entrada é avaliado em relação a todas as etapas em ordem inversa, da última etapa à primeira. When a record r is evaluated against some step s_k, the following logic is applied:
Check 1: If the state of the previous step (s_k-1) is nonempty, and r meets the Condition of s_k, then a match occurs. A correspondência leva às seguintes ações:
- The state of s_k is cleared.
- The state of s_k-1 is promoted to become the state of s_k.
- The assignments of s_k are calculated and extend r.
- The extended r is added to the output and to the state of s_k.
Note
If Check 1 results in a match, Check 2 is disregarded, and r moves on to be evaluated against s_k-1.
Check 2: If the state of s_k has an active sequence or s_k is the first step, and r meets the Condition of s_k, then a match occurs. A correspondência leva às seguintes ações:
- The assignments of s_k are calculated and extend r.
- The values that represent s_k in the state of s_k are replaced with the values of the extended r.
- If s_k is defined as
output=all, the extended r is added to the output. - If s_k is the first step, a new sequence begins and the match ID increases by
1. Isso só afeta a saída quandowith_match_idé usada.
Once the checks for s_k are complete, r moves on to be evaluated against s_k-1.
Para obter um exemplo detalhado dessa lógica, consulte o passo a passo da lógica de verificação .
Examples
O exemplo nesta seção mostra como usar a sintaxe para ajudá-lo a começar.
The examples in this article use publicly available tables in the help cluster, such as the
StormEventstable in the Samples database.
The examples in this article use publicly available tables, such as the
Weathertable in the Weather analytics sample gallery. Talvez seja necessário modificar o nome da tabela na consulta de exemplo para corresponder à tabela em seu espaço de trabalho.
Cumulative sum
Calcule a soma cumulativa de uma coluna de entrada. The result of this example is equivalent to using 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 |
Soma cumulativa em várias colunas com uma condição de redefinição
Calcule a soma acumulada para duas colunas de entrada, redefina o valor da soma para o valor de registro atual sempre que a soma acumulada atingir 10 ou mais.
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 |
Preencher uma coluna
Preencha uma coluna de cadeia de caracteres. A cada valor vazio é atribuído o último valor não vazio visto.
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 |
Sessions tagging
Divida a entrada em sessões: uma sessão termina 30 minutos após o primeiro evento da sessão, após o qual uma nova sessão começa. Note the use of with_match_id flag, which assigns a unique value for each distinct match (session) of scan. Also note the special use of two steps in this example, inSession has true as condition so it captures and outputs all the records from the input while endSession captures records that happen more than 30m from the sessionStart value for the current match. A etapa endSession tem output=none significa que não produz registros de saída. A etapa endSession é usada para avançar o estado da partida atual de inSession para endSession, permitindo que uma nova partida (sessão) comece, a partir do registro atual.
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 |
Calculando a duração da sessão por usuário
Calcule a hora de início, a hora de término e a duração da sessão de cada usuário usando o scan operador. Uma sessão é definida como um período entre o login de um usuário e o logout subsequente. Ao combinar partition e scan com e output=none, output=all esse padrão garante que uma única linha seja retornada por sessão (ou seja, por par de login/logout), em vez de uma linha por evento.
A lógica funciona por:
- Na etapa s1: Capturando o carimbo de data/hora de login usando uma etapa de verificação com
output=none - Na etapa s2: Emitindo uma linha somente quando um logout correspondente é encontrado usando
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 |
Eventos entre Iniciar e Parar
Encontre todas as sequências de eventos entre o Start de eventos e os Stop de eventos que ocorrem dentro de 5 minutos. Atribua um ID de correspondência para cada sequência.
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 |
Calcular um funil personalizado de eventos
Calcule uma conclusão de funil da sequência Hail ->Tornado ->Thunderstorm Wind por State com limites personalizados nos tempos entre os eventos (Tornado dentro de 1h e Thunderstorm Wind dentro de 2h). This example is similar to the funnel_sequence_completion plugin, but allows greater flexibility.
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 |
| Thunderstorm Wind | 32 |
Passo a passo da lógica de varredura
This section demonstrates the scan logic using a step-by-step walkthrough of the Events between start and stop example:
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 |
The state
Pense no estado do operador scan como uma tabela com uma linha para cada etapa, na qual cada etapa tem seu próprio estado. Esse estado contém os valores mais recentes das colunas e variáveis declaradas de todas as etapas anteriores e da etapa atual. To learn more, see State.
Neste exemplo, o estado pode ser representado com a seguinte tabela:
| step | m_id | s1.Ts | s1.Event | s2.Ts | s2.Event | s3.Ts | s3.Event |
|---|---|---|---|---|---|---|---|
| s1 | X | X | X | X | |||
| s2 | X | X | |||||
| s3 |
O "X" indica que um campo específico é irrelevante para essa etapa.
A lógica de correspondência
This section follows the matching logic through each record of the Events table, explaining the transformation of the state and output at each step.
Note
Um registro de entrada é avaliado em relação às etapas em ordem inversa, da última etapa (s3) para a primeira etapa (s1).
Record 1
| Ts | Event |
|---|---|
| 0m | "A" |
Registar a avaliação em cada etapa:
-
s3: Check 1 isn't passed because the state ofs2is empty, and Check 2 isn't passed becauses3lacks an active sequence. -
s2: Check 1 isn't passed because the state ofs1is empty, and Check 2 isn't passed becauses2lacks an active sequence. -
s1: Check 1 is irrelevant because there's no previous step. Check 2 isn't passed because the record doesn't meet the condition ofEvent == "Start". Record 1 is discarded without affecting the state or output.
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 |
Record 2
| Ts | Event |
|---|---|
| 1m | "Start" |
Registar a avaliação em cada etapa:
-
s3: Check 1 isn't passed because the state ofs2is empty, and Check 2 isn't passed becauses3lacks an active sequence. -
s2: Check 1 isn't passed because the state ofs1is empty, and Check 2 isn't passed becauses2lacks an active sequence. -
s1: Check 1 is irrelevant because there's no previous step. Check 2 is passed because the record meets the condition ofEvent == "Start". Essa correspondência inicia uma nova sequência e om_idé atribuído. Record 2 and itsm_id(0) are added to the state and the output.
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 |
Record 3
| Ts | Event |
|---|---|
| 2m | "B" |
Registar a avaliação em cada etapa:
-
s3: Check 1 isn't passed because the state ofs2is empty, and Check 2 isn't passed becauses3lacks an active sequence. -
s2: Check 1 is passed because the state ofs1is nonempty and the record meets the condition ofTs - s1.Ts < 5m. Essa correspondência faz com que o estado des1seja limpo e a sequência ems1seja promovida paras2. Record 3 and itsm_id(0) are added to the state and the output. -
s1: Check 1 is irrelevant because there's no previous step, and Check 2 isn't passed because the record doesn't meet the condition ofEvent == "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 |
Record 4
| Ts | Event |
|---|---|
| 3m | "D" |
Registar a avaliação em cada etapa:
-
s3: Check 1 isn't passed because the record doesn't meet the condition ofEvent == "Stop", and Check 2 isn't passed becauses3lacks an active sequence. -
s2: Check 1 isn't passed because the state ofs1is empty. it passes Check 2 because it meets the condition ofTs - s1.Ts < 5m. Record 4 and itsm_id(0) are added to the state and the output. Os valores desse registro substituem os valores de estado anteriores paras2.Tses2.Event. -
s1: Check 1 is irrelevant because there's no previous step, and Check 2 isn't passed because the record doesn't meet the condition ofEvent == "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 |
Record 5
| Ts | Event |
|---|---|
| 4m | "Stop" |
Registar a avaliação em cada etapa:
-
s3: Check 1 is passed becauses2is nonempty and it meets thes3condition ofEvent == "Stop". Essa correspondência faz com que o estado des2seja limpo e a sequência ems2seja promovida paras3. Record 5 and itsm_id(0) are added to the state and the output. -
s2: Check 1 isn't passed because the state ofs1is empty, and Check 2 isn't passed becauses2lacks an active sequence. -
s1: Check 1 is irrelevant because there's no previous step. Check 2 isn't passed because the record doesn't meet the condition ofEvent == "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" |
Record 6
| Ts | Event |
|---|---|
| 6m | "C" |
Registar a avaliação em cada etapa:
-
s3: Check 1 isn't passed because the state ofs2is empty, and Check 2 isn't passed becauses3doesn't meet thes3condition ofEvent == "Stop". -
s2: Check 1 isn't passed because the state ofs1is empty, and Check 2 isn't passed becauses2lacks an active sequence. -
s1: Check 1 isn't passed because there's no previous step, and Check 2 isn't passed because it doesn't meet the condition ofEvent == "Start". Record 6 is discarded without affecting the state or output.
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" |
Record 7
| Ts | Event |
|---|---|
| 8m | "Start" |
Registar a avaliação em cada etapa:
-
s3: Check 1 isn't passed because the state ofs2is empty, and Check 2 isn't passed because it doesn't meet the condition ofEvent == "Stop". -
s2: Check 1 isn't passed because the state ofs1is empty, and Check 2 isn't passed becauses2lacks an active sequence. -
s1: Check 1 isn't passed because there's no previous step. it passes Check 2 because it meets the condition ofEvent == "Start". Esta partida inicia uma nova sequência ems1com um novom_id. Record 7 and itsm_id(1) are added to the state and the output.
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
Agora há duas sequências ativas no estado.
Record 8
| Ts | Event |
|---|---|
| 11m | "E" |
Registar a avaliação em cada etapa:
-
s3: Check 1 isn't passed because the state ofs2is empty, and Check 2 isn't passed because it doesn't meet thes3condition ofEvent == "Stop". -
s2: Check 1 is passed because the state ofs1is nonempty and the record meets the condition ofTs - s1.Ts < 5m. Essa correspondência faz com que o estado des1seja limpo e a sequência ems1seja promovida paras2. Record 8 and itsm_id(1) are added to the state and the output. -
s1: Check 1 is irrelevant because there's no previous step, and Check 2 isn't passed because the record doesn't meet the condition ofEvent == "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" |
Record 9
| Ts | Event |
|---|---|
| 12m | "Stop" |
Registar a avaliação em cada etapa:
-
s3: Check 1 is passed becauses2is nonempty and it meets thes3condition ofEvent == "Stop". Essa correspondência faz com que o estado des2seja limpo e a sequência ems2seja promovida paras3. Record 9 and itsm_id(1) are added to the state and the output. -
s2: Check 1 isn't passed because the state ofs1is empty, and Check 2 isn't passed becauses2lacks an active sequence. -
s1: Check 1 isn't passed because there's no previous step. it passes Check 2 because it meets the condition ofEvent == "Start". Esta partida inicia uma nova sequência ems1com um novom_id.
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" |
Final 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 |