有关在 Azure 门户中使用这些查询的信息,请参阅 Log Analytics 教程。 有关 REST API,请参阅 查询。
案例的最新更改
显示特定案例的最后 10 个字段级更改,包括谁进行了更改和修改的内容。
// Last 10 changes on a specific case (including child entities like tasks, comments, attachments).
// Each row represents one event. Note: a single user action may produce multiple rows
// (one per property changed).
//
// Replace the placeholder below with a case ID
let targetCaseId = '<replace-with-case-id>';
SecurityCaseEvent
| where TimeGenerated >= ago(90d)
| where EntityId == targetCaseId or ParentEntityId == targetCaseId
//| where EntityType == 'Case' // Uncomment to show only case-level changes (no tasks/comments)
//| where OperationName == 'Update' // Uncomment to show only updates (no creates/deletes)
| project EventTime, ModifiedBy, OperationName, EntityType, EntityId, PropertyNames, NewValues
| order by EventTime desc
| take 10
按状态排序的事例
通过重播“创建”和“更新”事件查找当前状态与特定值匹配的所有情况。
// Find all cases where the current status matches a specific value.
// Replays Create/Update events to determine each case's latest status.
//
// Replace the placeholder below with the status value to match (e.g. 'Active', 'InProgress')
let targetStatus = '<replace-with-status-value>';
// --- Exclude deleted cases ---
let deletedCases = SecurityCaseEvent
| where TimeGenerated >= ago(30d)
| where EntityType == 'Case'
| where IsDeleted == true
| distinct EntityId;
// --- Determine each case's latest status and type ---
SecurityCaseEvent
| where TimeGenerated >= ago(30d)
| where EntityType == 'Case'
| where OperationName in ('Create', 'Update')
| where EntityId !in (deletedCases)
// mv-expand: expands array properties into individual rows per property change
| mv-expand PropertyNames, NewValues
| extend PropName = tostring(PropertyNames), PropValue = tostring(NewValues)
| where PropName in ('caseStatus.statusName', 'caseType')
// arg_max: keeps only the most recent value per case per property
| summarize arg_max(EventTime, PropValue) by EntityId, PropName
| summarize
Status = take_anyif(PropValue, PropName == 'caseStatus.statusName'),
CaseType = take_anyif(PropValue, PropName == 'caseType')
by EntityId
| where isnotempty(Status)
| where tolower(Status) == tolower(targetStatus)
//| where tolower(Status) != tolower(targetStatus) // Uncomment to exclude this status instead
//| where CaseType == '<case-type>' // Uncomment to filter by case type
| project EntityId, Status, CaseType
具有大多数打开任务的情况
按打开的任务数对事例进行排名,不包括已删除的任务和事例。
// Ranks cases by number of open tasks, excluding deleted tasks and cases.
//
// --- Exclude deleted cases and tasks ---
let deletedCases = SecurityCaseEvent
| where TimeGenerated >= ago(90d)
| where EntityType == 'Case'
| where IsDeleted == true
| distinct EntityId;
let deletedTasks = SecurityCaseEvent
| where TimeGenerated >= ago(90d)
| where EntityType == 'CaseTask'
| where IsDeleted == true
| distinct EntityId;
// --- Find the latest status of each task and count open ones per case ---
SecurityCaseEvent
| where TimeGenerated >= ago(90d)
| where EntityType == 'CaseTask'
| where OperationName in ('Create', 'Update')
| where EntityId !in (deletedTasks)
| where ParentEntityId !in (deletedCases)
// mv-expand: expands array properties into individual rows
| mv-expand PropertyNames, NewValues
| extend Status = tostring(NewValues)
| where PropertyNames == 'status'
// arg_max: keeps the latest status value per task
| summarize arg_max(EventTime, Status) by EntityId, ParentEntityId
// Keep only open tasks
| where tolower(Status) !in ('completed', 'skipped', 'failed')
//| where tolower(Status) == 'inprogress' // Uncomment to count only in-progress tasks
| summarize OpenTaskCount = count() by CaseId = ParentEntityId
| order by OpenTaskCount desc
非活动案例
查找过去 7 天内没有活动(包括子实体活动)的事例,不包括最近创建和删除的事例。
// Cases with no activity in the last 7 days (excluding deleted and closed cases).
// "Activity" includes any event on the case itself or its child entities (tasks, comments, etc.).
//
// Parameters you can adjust:
let creationWindow = 21d; // How far back to look for case creation
let inactiveDays = 7d; // How many days of silence counts as "inactive"
//
// --- Exclude deleted cases ---
let deletedCases = SecurityCaseEvent
| where TimeGenerated >= ago(creationWindow)
| where EntityType == 'Case'
| where IsDeleted == true
| distinct EntityId;
// --- Exclude closed cases (based on latest topLevelStatusName) ---
let closedCases = SecurityCaseEvent
| where TimeGenerated >= ago(creationWindow)
| where EntityType == 'Case'
| where OperationName in ('Create', 'Update')
| mv-expand PropertyNames, NewValues
| extend PropName = tostring(PropertyNames), PropValue = tostring(NewValues)
| where PropName == 'caseStatus.topLevelStatusName'
// arg_max: get the most recent status value per case
| summarize arg_max(EventTime, PropValue) by EntityId
| where tolower(PropValue) == 'closed'
| distinct EntityId;
// --- All candidate cases: created within the window but old enough to be "inactive" ---
let allCases = SecurityCaseEvent
| where TimeGenerated >= ago(creationWindow)
| where EntityType == 'Case'
| where OperationName == 'Create'
| where EventTime between (ago(creationWindow) .. ago(inactiveDays))
| where EntityId !in (deletedCases)
| where EntityId !in (closedCases)
| distinct CaseId = EntityId;
// --- Find last activity time per case and determine if active (including child entity activity) ---
let caseActivity = SecurityCaseEvent
| where TimeGenerated >= ago(creationWindow)
// For child entities, map back to the parent case
| extend CaseId = iff(EntityType == 'Case', EntityId, ParentEntityId)
| where isnotempty(CaseId)
| summarize LastActivityTime = max(EventTime) by CaseId;
// --- Look up CaseType for each case ---
let caseTypes = SecurityCaseEvent
| where TimeGenerated >= ago(creationWindow)
| where EntityType == 'Case'
| where OperationName in ('Create', 'Update')
| mv-expand PropertyNames, NewValues
| extend PropName = tostring(PropertyNames), PropValue = tostring(NewValues)
| where PropName == 'caseType'
| summarize arg_max(EventTime, PropValue) by EntityId
| project EntityId, CaseType = PropValue;
// --- Result: cases with zero recent activity ---
allCases
| join kind=leftouter caseActivity on CaseId
| where LastActivityTime < ago(inactiveDays)
| join kind=leftouter caseTypes on $left.CaseId == $right.EntityId
//| where CaseType == '<case-type>' // Uncomment to filter by case type
| project EntityId = CaseId, CaseType, LastActivityTime
| order by LastActivityTime asc
紧急开放案例
列出处于关闭状态的严重或高优先级的事例。
// Cases with Critical or High priority that are not closed.
// Reconstructs the latest property values per case, then filters for
// urgent (High/Critical) cases that remain open.
//
// --- Exclude deleted cases ---
let deletedCases = SecurityCaseEvent
| where TimeGenerated >= ago(90d)
| where EntityType == 'Case'
| where IsDeleted == true
| distinct EntityId;
// --- Reconstruct latest case properties via pivot ---
let CaseProperties =
SecurityCaseEvent
| where TimeGenerated >= ago(90d)
| where EntityType == 'Case'
| where OperationName in ('Create', 'Update')
| where EntityId !in (deletedCases)
// mv-expand: expands array properties into individual rows per property change
| mv-expand PropertyNames, NewValues
| extend PropName = tostring(PropertyNames), PropValue = tostring(NewValues)
| extend NormProp = case(
PropName in ('priority', 'severity'), 'Priority',
PropName == 'caseStatus.statusName', 'Status',
PropName == 'caseStatus.topLevelStatusName', 'TopLevelStatus',
PropName == 'displayName', 'DisplayName',
PropName == 'caseType', 'CaseType',
'')
| where NormProp != ''
// arg_max: keeps the most recent value per case per property
| summarize arg_max(EventTime, PropValue) by EntityId, NormProp
// project before pivot to avoid unintended grouping on EventTime
| project EntityId, NormProp, PropValue
// evaluate pivot: turns rows into columns (one column per property)
| evaluate pivot(NormProp, take_any(PropValue));
// --- Filter and output ---
// column_ifexists: safely accesses pivot columns that may not exist if no case has that property
CaseProperties
| extend
Priority = tostring(column_ifexists('Priority', '')),
Status = tostring(column_ifexists('Status', '')),
TopLevelStatus = tostring(column_ifexists('TopLevelStatus', '')),
DisplayName = tostring(column_ifexists('DisplayName', '')),
CaseType = tostring(column_ifexists('CaseType', ''))
| where tolower(Priority) in ('high', 'critical')
| where tolower(Status) !in ('closed') and tolower(TopLevelStatus) !in ('closed')
//| where tolower(Priority) == 'critical' // Uncomment to show only Critical
//| where CaseType == '<case-type>' // Uncomment to filter by case type
//| where AssignedTo has '<user>' // Uncomment to filter by assignee
| project EntityId, DisplayName, Priority, Status, TopLevelStatus, CaseType
| order by Priority asc
具有逾期任务的情况
标识已打开任务超过截止日期的事例,按过期的任务计数进行排名。
// Cases with open tasks past their due date, ranked by overdue count.
// Replays task property events to find each task's latest status and due date,
// then filters for tasks that are open and past due.
//
// --- Exclude deleted cases and tasks ---
let deletedCases = SecurityCaseEvent
| where TimeGenerated >= ago(90d)
| where EntityType == 'Case'
| where IsDeleted == true
| distinct EntityId;
let deletedTasks = SecurityCaseEvent
| where TimeGenerated >= ago(90d)
| where EntityType == 'CaseTask'
| where IsDeleted == true
| distinct EntityId;
// --- Reconstruct latest task properties via pivot ---
SecurityCaseEvent
| where TimeGenerated >= ago(90d)
| where EntityType == 'CaseTask'
| where OperationName in ('Create', 'Update')
| where EntityId !in (deletedTasks)
| where ParentEntityId !in (deletedCases)
// mv-expand: expands array properties into individual rows per property change
| mv-expand PropertyNames, NewValues
| extend PropertyValue = tostring(NewValues)
// Map only the properties we need for this query
| extend PivotProperty = case(
PropertyNames == 'status', 'status',
PropertyNames == 'dueDateTime', 'dueDateTime',
''
)
| where PivotProperty != ''
// arg_max: keeps the most recent value of each property per task
| summarize arg_max(EventTime, PropertyValue) by TaskId = EntityId, CaseId = ParentEntityId, PivotProperty
// project before pivot to avoid unintended grouping on EventTime
| project TaskId, CaseId, PivotProperty, PropertyValue
// evaluate pivot: transforms rows into columns (one column for 'status', one for 'dueDateTime')
| evaluate pivot(PivotProperty, take_any(PropertyValue))
// column_ifexists: safely accesses a column that may not exist if no task ever had that property set
| extend status = tostring(column_ifexists('status', '')),
dueDateTime = tostring(column_ifexists('dueDateTime', ''))
| where isnotempty(CaseId)
// Filter for open tasks only (exclude completed/skipped/failed)
| where tolower(status) !in ('completed', 'skipped', 'failed')
// Filter for tasks past their due date
| where todatetime(dueDateTime) < now()
//| where todatetime(dueDateTime) < ago(7d) // Uncomment to find tasks overdue by more than 7 days
| summarize OverdueTaskCount = count(), EarliestDueDate = min(todatetime(dueDateTime)) by CaseId
| order by OverdueTaskCount desc
每天创建的案例任务
过去 30 天内创建的新任务的每日计数。
// Daily task creation volume over the last 30 days.
// Simple trend query — useful for spotting spikes in workload.
SecurityCaseEvent
| where TimeGenerated >= ago(30d)
| where EntityType == "CaseTask"
| where OperationName == "Create"
//| where ParentEntityId == '<case-id>' // Uncomment to filter by a specific case
| summarize TasksCreated = count() by Day = startofday(EventTime)
| order by Day
特定用户的所有案例管理活动
显示过去 30 天内特定用户的所有案例管理活动(案例、任务、关系),按案例分组。
// All case management activity (cases, tasks, relations) by a specific user in the last 30 days, grouped by case.
// Shows the time range and types of operations each user performed on each case.
//
// Replace the placeholder below with a user alias or UPN
let targetUser = '<replace-with-user-alias>';
let timeRange = 30d; // Adjust to widen/narrow the search window
SecurityCaseEvent
| where TimeGenerated >= ago(timeRange)
| where ModifiedBy has targetUser
// Map child entities (tasks, comments, etc.) back to their parent case
| extend CaseId = iff(EntityType == 'Case', EntityId, ParentEntityId)
| where isnotempty(CaseId)
| summarize
FirstEvent = min(EventTime),
LastEvent = max(EventTime),
OperationsSet = make_set(OperationName),
EntityTypes = make_set(EntityType)
by CaseId
//| where OperationsSet has 'Delete' // Uncomment to show only cases where user performed deletions
//| where EntityTypes has 'CaseTask' // Uncomment to show only cases where user touched tasks
| order by LastEvent desc
分配给特定用户的事例和任务
查找当前分配给特定用户的所有事例和任务,不包括已删除的实体。
// All cases and tasks currently assigned to a specific user.
// Replays 'assignedTo' property changes to find the latest assignment per entity.
//
// Replace the placeholder below with a user alias or UPN
let targetUser = '<replace-with-user-alias>';
// --- Exclude deleted cases and tasks ---
let deletedCases = SecurityCaseEvent
| where TimeGenerated >= ago(90d)
| where EntityType == 'Case'
| where IsDeleted == true
| distinct EntityId;
let deletedTasks = SecurityCaseEvent
| where TimeGenerated >= ago(90d)
| where EntityType == 'CaseTask'
| where IsDeleted == true
| distinct EntityId;
// --- Find the latest 'assignedTo' value for each case and task ---
SecurityCaseEvent
| where TimeGenerated >= ago(90d)
| where EntityType in ('Case', 'CaseTask')
| where OperationName in ('Create', 'Update')
| extend CaseId = iff(EntityType == 'Case', EntityId, ParentEntityId)
| where CaseId !in (deletedCases)
| where EntityId !in (deletedTasks)
// mv-expand: expands array properties into individual rows per property change
| mv-expand PropertyNames, NewValues
| extend
PropertyName = tostring(PropertyNames),
PropertyValue = tostring(NewValues)
| where PropertyName == 'assignedTo'
// arg_max: keeps the most recent assignment per entity
| summarize arg_max(EventTime, PropertyValue, CaseId) by EntityType, EntityId
| where PropertyValue has targetUser
//| where EntityType == 'CaseTask' // Uncomment to show only tasks
| project
EntityType,
EntityId,
CaseId,
AssignedTo = PropertyValue,
LastAssignmentTime = EventTime
| order by LastAssignmentTime desc
具有大多数打开案例任务的用户
对分配给每个用户的打开任务进行计数,不包括已删除的任务和事例。
// Users ranked by number of open tasks assigned to them.
// Reconstructs each task's latest status and assignee, then counts open tasks per user.
//
// --- Exclude deleted cases and tasks ---
let deletedCases = SecurityCaseEvent
| where TimeGenerated >= ago(90d)
| where EntityType == 'Case'
| where IsDeleted == true
| distinct EntityId;
let deletedTasks = SecurityCaseEvent
| where TimeGenerated >= ago(90d)
| where EntityType == 'CaseTask'
| where IsDeleted == true
| distinct EntityId;
// --- Reconstruct latest task properties via pivot ---
SecurityCaseEvent
| where TimeGenerated >= ago(90d)
| where EntityType == 'CaseTask'
| where OperationName in ('Create', 'Update')
| where EntityId !in (deletedTasks)
| where ParentEntityId !in (deletedCases)
// mv-expand: expands array properties into individual rows per property change
| mv-expand PropertyNames, NewValues
| extend PropertyValue = tostring(NewValues)
// Map only the properties we care about
| extend PivotProperty = case(
PropertyNames == 'status', 'status',
PropertyNames == 'assignedTo', 'assignedTo',
''
)
| where PivotProperty != ''
// arg_max: keeps the most recent value of each property per task
| summarize arg_max(EventTime, PropertyValue) by TaskId = EntityId, PivotProperty
// project before pivot to avoid unintended grouping on EventTime
| project TaskId, PivotProperty, PropertyValue
// evaluate pivot: transforms rows into columns (one for 'status', one for 'assignedTo')
| evaluate pivot(PivotProperty, take_any(PropertyValue))
// column_ifexists: safely accesses columns that may not exist if no task has that property
| extend status = column_ifexists('status', dynamic(null)),
assignedTo = tostring(column_ifexists('assignedTo', 'Unassigned'))
// Keep only open tasks (exclude completed/skipped/failed)
| where tolower(tostring(status)) !in ('completed', 'skipped', 'failed') or isnull(status)
| extend assignedTo = iff(isempty(assignedTo), 'Unassigned', assignedTo)
| where assignedTo != 'Unassigned'
//| where assignedTo has '<user>' // Uncomment to filter for a specific user
| summarize OpenTaskCount = count() by assignedTo
| order by OpenTaskCount desc
完整事例快照(所有事例)
重新构造时间范围内所有事例的当前状态,包括任务、注释、附件、标记和关系作为 JSON 数组。
// Reconstruct the current state of ALL cases changed within a time window, including child entities.
// Same approach as SingleCaseSnapshot but without filtering to a specific case ID.
// Output: one row per case with Tasks, Comments, Attachments, Tags, and Relations as JSON arrays.
//
// How it works:
// 1. Find all non-deleted cases with events in the lookback window
// 2. For each case property, find the latest value via arg_max
// 3. Repeat for child entities (tasks, comments, attachments, relations)
// 4. Join into a single row per case
//
let lookback = 90d;
//
// ============ STEP 1: Identify non-deleted cases ============
let deletedCases = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'Case'
| where IsDeleted == true
| distinct EntityId;
let ChangedCaseIds = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'Case'
| where EntityId !in (deletedCases)
| distinct CaseId = EntityId;
//
// ============ STEP 2: Reconstruct case-level properties ============
let CaseSnapshot = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'Case'
| where IsDeleted == false
| where EntityId in (ChangedCaseIds)
| where OperationName in ('Create', 'Update')
| mv-expand PropertyNames, NewValues
| extend PropName = tostring(PropertyNames), PropValue = tostring(NewValues)
// arg_max: for each property, keep the value from the most recent event
| summarize arg_max(EventTime, PropValue, EntityCreatedTime) by EntityId, PropName
| summarize
DisplayName = take_anyif(PropValue, PropName == 'displayName'),
StatusName = take_anyif(PropValue, PropName == 'caseStatus.statusName'),
TopLevelStatus = take_anyif(PropValue, PropName == 'caseStatus.topLevelStatusName'),
Severity = take_anyif(PropValue, PropName == 'severity'), // Incident cases
Priority = take_anyif(PropValue, PropName == 'priority'), // Default cases
AssignedTo = take_anyif(PropValue, PropName == 'assignedTo'),
Classification = take_anyif(PropValue, PropName == 'classification'),
Determination = take_anyif(PropValue, PropName == 'determination'),
Description = take_anyif(PropValue, PropName == 'description'),
CaseType = take_anyif(PropValue, PropName == 'caseType'),
CreatedTime = take_anyif(PropValue, PropName == 'createdTime'),
EntityCreatedTime = take_any(EntityCreatedTime),
CustomFields = take_anyif(PropValue, PropName == 'customFields'),
ClosingNotes = take_anyif(PropValue, PropName == 'closingNotes'),
SlaAssignmentStatus = take_anyif(PropValue, PropName == 'sla.assignmentStatus'),
SlaResolutionStatus = take_anyif(PropValue, PropName == 'sla.resolutionStatus'),
SlaPolicyName = take_anyif(PropValue, PropName == 'sla.policyName'),
SlaPolicyId = take_anyif(PropValue, PropName == 'sla.policyId'),
SlaPolicyAppliedDateTime = take_anyif(PropValue, PropName == 'sla.policyAppliedDateTime')
by EntityId;
//
// ============ STEP 3: Reconstruct child entities ============
// --- Tasks ---
let ActiveTasks = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'CaseTask'
| where ParentEntityId in (ChangedCaseIds)
| summarize arg_max(EventTime, IsDeleted, OperationName) by EntityId
| where IsDeleted == false and OperationName != 'Delete'
| project TaskId = EntityId;
let TasksJson = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'CaseTask'
| where EntityId in (ActiveTasks)
| where OperationName in ('Create', 'Update')
| mv-expand PropertyNames, NewValues
| extend PropName = tostring(PropertyNames), PropValue = tostring(NewValues)
| summarize arg_max(EventTime, PropValue, EntityCreatedTime) by EntityId, ParentEntityId, PropName
| summarize TaskProps = make_bag(pack(PropName, PropValue)), EntityCreatedTime = take_any(EntityCreatedTime) by TaskId = EntityId, CaseId = ParentEntityId
| extend Task = bag_merge(TaskProps, bag_pack('taskId', TaskId, 'entityCreatedTime', tostring(EntityCreatedTime)))
| summarize Tasks = make_list(Task) by EntityId = CaseId;
// --- Comments ---
let ActiveComments = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'CaseComment'
| where ParentEntityId in (ChangedCaseIds)
| summarize arg_max(EventTime, IsDeleted, OperationName) by EntityId
| where IsDeleted == false and OperationName != 'Delete'
| project CommentId = EntityId;
let CommentsJson = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'CaseComment'
| where EntityId in (ActiveComments)
| where OperationName in ('Create', 'Update')
| mv-expand PropertyNames, NewValues
| extend PropName = tostring(PropertyNames), PropValue = tostring(NewValues)
| summarize arg_max(EventTime, PropValue, EntityCreatedTime) by EntityId, ParentEntityId, PropName
| summarize CommentProps = make_bag(pack(PropName, PropValue)), EntityCreatedTime = take_any(EntityCreatedTime) by CommentId = EntityId, CaseId = ParentEntityId
| extend Comment = bag_merge(CommentProps, bag_pack('commentId', CommentId, 'entityCreatedTime', tostring(EntityCreatedTime)))
| summarize Comments = make_list(Comment) by EntityId = CaseId;
// --- Attachments ---
let ActiveAttachments = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'CaseAttachment'
| where ParentEntityId in (ChangedCaseIds)
| summarize arg_max(EventTime, IsDeleted, OperationName) by EntityId
| where IsDeleted == false and OperationName != 'Delete'
| project AttachmentId = EntityId;
let AttachmentsJson = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'CaseAttachment'
| where EntityId in (ActiveAttachments)
| where OperationName in ('Create', 'Update')
| mv-expand PropertyNames, NewValues
| extend PropName = tostring(PropertyNames), PropValue = tostring(NewValues)
| summarize arg_max(EventTime, PropValue, EntityCreatedTime) by EntityId, ParentEntityId, PropName
| summarize AttachmentProps = make_bag(pack(PropName, PropValue)), EntityCreatedTime = take_any(EntityCreatedTime) by AttachmentId = EntityId, CaseId = ParentEntityId
| extend Attachment = bag_merge(AttachmentProps, bag_pack('attachmentId', AttachmentId, 'entityCreatedTime', tostring(EntityCreatedTime)))
| summarize Attachments = make_list(Attachment) by EntityId = CaseId;
// --- Tags ---
let CaseTags = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'Case'
| where EntityId in (ChangedCaseIds)
| where OperationName in ('Create', 'Update')
| where PropertyNames has 'tags'
| extend TagIdx = array_index_of(PropertyNames, 'tags')
| extend Tags = iff(TagIdx >= 0, NewValues[TagIdx], NewValues)
| summarize arg_max(EventTime, Tags) by EntityId
| project EntityId, Tags;
// --- Relations ---
let ActiveRelations = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'CaseRelation'
| where ParentEntityId in (ChangedCaseIds)
| summarize arg_max(EventTime, IsDeleted, OperationName) by EntityId
| where IsDeleted == false and OperationName !in ('Delete', 'Unlink')
| project RelationId = EntityId;
let RelationsJson = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'CaseRelation'
| where EntityId in (ActiveRelations)
| where OperationName in ('Create', 'Update', 'Link')
| mv-expand PropertyNames, NewValues
| extend PropName = tostring(PropertyNames), PropValue = tostring(NewValues)
| summarize arg_max(EventTime, PropValue, EntityCreatedTime) by EntityId, ParentEntityId, PropName
| summarize RelationProps = make_bag(pack(PropName, PropValue)), EntityCreatedTime = take_any(EntityCreatedTime) by RelationId = EntityId, CaseId = ParentEntityId
| extend Relation = bag_merge(RelationProps, bag_pack('relationId', RelationId, 'entityCreatedTime', tostring(EntityCreatedTime)))
| summarize Relations = make_list(Relation) by EntityId = CaseId;
//
// ============ STEP 4: Join all pieces into final output ============
CaseSnapshot
| join kind=leftouter TasksJson on EntityId
| join kind=leftouter CommentsJson on EntityId
| join kind=leftouter AttachmentsJson on EntityId
| join kind=leftouter RelationsJson on EntityId
| join kind=leftouter CaseTags on EntityId
| project
EntityId, DisplayName, StatusName, TopLevelStatus, Severity, Priority,
AssignedTo, Classification, Determination, Description,
Tags = coalesce(Tags, dynamic([])), CaseType, CreatedTime, EntityCreatedTime, CustomFields, ClosingNotes,
SlaAssignmentStatus, SlaResolutionStatus, SlaPolicyName, SlaPolicyId, SlaPolicyAppliedDateTime,
Tasks = coalesce(Tasks, dynamic([])),
Comments = coalesce(Comments, dynamic([])),
Attachments = coalesce(Attachments, dynamic([])),
Relations = coalesce(Relations, dynamic([]))
单案例快照
重新构造单个事例的完整当前状态,包括所有子实体。
// Reconstruct the complete current state of a single case including all child entities.
// This query replays all events to build a full "snapshot" of a case as it exists now,
// including tasks, comments, attachments, tags, and relations as JSON arrays.
//
// How it works:
// 1. Identify the target case (exclude if deleted)
// 2. For each property, find the latest value via arg_max (most recent event wins)
// 3. Repeat for each child entity type (tasks, comments, attachments, relations)
// 4. Join everything together into a single output row per case
//
// Replace with the case ID you want to inspect
let targetCaseId = '<replace-with-case-id>';
let lookback = 90d;
//
// ============ STEP 1: Exclude deleted cases ============
let deletedCases = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'Case'
| where IsDeleted == true
| distinct EntityId;
let ChangedCaseIds = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'Case'
| where EntityId == targetCaseId
| where EntityId !in (deletedCases)
| distinct CaseId = EntityId;
//
// ============ STEP 2: Reconstruct case-level properties ============
let CaseSnapshot = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'Case'
| where IsDeleted == false
| where EntityId in (ChangedCaseIds)
| where OperationName in ('Create', 'Update')
// mv-expand: expand array properties into one row per property
| mv-expand PropertyNames, NewValues
| extend PropName = tostring(PropertyNames), PropValue = tostring(NewValues)
// arg_max: for each property, keep the value from the most recent event
| summarize arg_max(EventTime, PropValue, EntityCreatedTime) by EntityId, PropName
// take_anyif: pivot properties into named columns
| summarize
DisplayName = take_anyif(PropValue, PropName == 'displayName'),
StatusName = take_anyif(PropValue, PropName == 'caseStatus.statusName'),
TopLevelStatus = take_anyif(PropValue, PropName == 'caseStatus.topLevelStatusName'),
Severity = take_anyif(PropValue, PropName == 'severity'), // Incident cases
Priority = take_anyif(PropValue, PropName == 'priority'), // Default cases
AssignedTo = take_anyif(PropValue, PropName == 'assignedTo'),
Classification = take_anyif(PropValue, PropName == 'classification'),
Determination = take_anyif(PropValue, PropName == 'determination'),
Description = take_anyif(PropValue, PropName == 'description'),
CaseType = take_anyif(PropValue, PropName == 'caseType'),
CreatedTime = take_anyif(PropValue, PropName == 'createdTime'),
EntityCreatedTime = take_any(EntityCreatedTime),
CustomFields = take_anyif(PropValue, PropName == 'customFields'),
ClosingNotes = take_anyif(PropValue, PropName == 'closingNotes'),
SlaAssignmentStatus = take_anyif(PropValue, PropName == 'sla.assignmentStatus'),
SlaResolutionStatus = take_anyif(PropValue, PropName == 'sla.resolutionStatus'),
SlaPolicyName = take_anyif(PropValue, PropName == 'sla.policyName'),
SlaPolicyId = take_anyif(PropValue, PropName == 'sla.policyId'),
SlaPolicyAppliedDateTime = take_anyif(PropValue, PropName == 'sla.policyAppliedDateTime')
by EntityId;
//
// ============ STEP 3: Reconstruct child entities ============
// --- Tasks ---
let ActiveTasks = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'CaseTask'
| where ParentEntityId in (ChangedCaseIds)
| summarize arg_max(EventTime, IsDeleted, OperationName) by EntityId
| where IsDeleted == false and OperationName != 'Delete'
| project TaskId = EntityId;
let TasksJson = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'CaseTask'
| where EntityId in (ActiveTasks)
| where OperationName in ('Create', 'Update')
| mv-expand PropertyNames, NewValues
| extend PropName = tostring(PropertyNames), PropValue = tostring(NewValues)
| summarize arg_max(EventTime, PropValue, EntityCreatedTime) by EntityId, ParentEntityId, PropName
// make_bag + bag_merge: pack all properties into a single JSON object per task
| summarize TaskProps = make_bag(pack(PropName, PropValue)), EntityCreatedTime = take_any(EntityCreatedTime) by TaskId = EntityId, CaseId = ParentEntityId
| extend Task = bag_merge(TaskProps, bag_pack('taskId', TaskId, 'entityCreatedTime', tostring(EntityCreatedTime)))
| summarize Tasks = make_list(Task) by EntityId = CaseId;
// --- Comments ---
let ActiveComments = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'CaseComment'
| where ParentEntityId in (ChangedCaseIds)
| summarize arg_max(EventTime, IsDeleted, OperationName) by EntityId
| where IsDeleted == false and OperationName != 'Delete'
| project CommentId = EntityId;
let CommentsJson = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'CaseComment'
| where EntityId in (ActiveComments)
| where OperationName in ('Create', 'Update')
| mv-expand PropertyNames, NewValues
| extend PropName = tostring(PropertyNames), PropValue = tostring(NewValues)
| summarize arg_max(EventTime, PropValue, EntityCreatedTime) by EntityId, ParentEntityId, PropName
| summarize CommentProps = make_bag(pack(PropName, PropValue)), EntityCreatedTime = take_any(EntityCreatedTime) by CommentId = EntityId, CaseId = ParentEntityId
| extend Comment = bag_merge(CommentProps, bag_pack('commentId', CommentId, 'entityCreatedTime', tostring(EntityCreatedTime)))
| summarize Comments = make_list(Comment) by EntityId = CaseId;
// --- Attachments ---
let ActiveAttachments = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'CaseAttachment'
| where ParentEntityId in (ChangedCaseIds)
| summarize arg_max(EventTime, IsDeleted, OperationName) by EntityId
| where IsDeleted == false and OperationName != 'Delete'
| project AttachmentId = EntityId;
let AttachmentsJson = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'CaseAttachment'
| where EntityId in (ActiveAttachments)
| where OperationName in ('Create', 'Update')
| mv-expand PropertyNames, NewValues
| extend PropName = tostring(PropertyNames), PropValue = tostring(NewValues)
| summarize arg_max(EventTime, PropValue, EntityCreatedTime) by EntityId, ParentEntityId, PropName
| summarize AttachmentProps = make_bag(pack(PropName, PropValue)), EntityCreatedTime = take_any(EntityCreatedTime) by AttachmentId = EntityId, CaseId = ParentEntityId
| extend Attachment = bag_merge(AttachmentProps, bag_pack('attachmentId', AttachmentId, 'entityCreatedTime', tostring(EntityCreatedTime)))
| summarize Attachments = make_list(Attachment) by EntityId = CaseId;
// --- Tags ---
let CaseTags = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'Case'
| where EntityId in (ChangedCaseIds)
| where OperationName in ('Create', 'Update')
| where PropertyNames has 'tags'
| extend TagIdx = array_index_of(PropertyNames, 'tags')
| extend Tags = iff(TagIdx >= 0, NewValues[TagIdx], NewValues)
| summarize arg_max(EventTime, Tags) by EntityId
| project EntityId, Tags;
// --- Relations ---
let ActiveRelations = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'CaseRelation'
| where ParentEntityId in (ChangedCaseIds)
| summarize arg_max(EventTime, IsDeleted, OperationName) by EntityId
| where IsDeleted == false and OperationName !in ('Delete', 'Unlink')
| project RelationId = EntityId;
let RelationsJson = SecurityCaseEvent
| where TimeGenerated >= ago(lookback)
| where EntityType == 'CaseRelation'
| where EntityId in (ActiveRelations)
| where OperationName in ('Create', 'Update', 'Link')
| mv-expand PropertyNames, NewValues
| extend PropName = tostring(PropertyNames), PropValue = tostring(NewValues)
| summarize arg_max(EventTime, PropValue, EntityCreatedTime) by EntityId, ParentEntityId, PropName
| summarize RelationProps = make_bag(pack(PropName, PropValue)), EntityCreatedTime = take_any(EntityCreatedTime) by RelationId = EntityId, CaseId = ParentEntityId
| extend Relation = bag_merge(RelationProps, bag_pack('relationId', RelationId, 'entityCreatedTime', tostring(EntityCreatedTime)))
| summarize Relations = make_list(Relation) by EntityId = CaseId;
//
// ============ STEP 4: Join all pieces into final output ============
CaseSnapshot
| join kind=leftouter TasksJson on EntityId
| join kind=leftouter CommentsJson on EntityId
| join kind=leftouter AttachmentsJson on EntityId
| join kind=leftouter RelationsJson on EntityId
| join kind=leftouter CaseTags on EntityId
| project
EntityId, DisplayName, StatusName, TopLevelStatus, Severity, Priority,
AssignedTo, Classification, Determination, Description,
Tags = coalesce(Tags, dynamic([])), CaseType, CreatedTime, EntityCreatedTime, CustomFields, ClosingNotes,
SlaAssignmentStatus, SlaResolutionStatus, SlaPolicyName, SlaPolicyId, SlaPolicyAppliedDateTime,
Tasks = coalesce(Tasks, dynamic([])),
Comments = coalesce(Comments, dynamic([])),
Attachments = coalesce(Attachments, dynamic([])),
Relations = coalesce(Relations, dynamic([]))
时间点单案例快照
在特定的历史时间戳(时间旅行)中重新构造案件的状态,从而对过去的案件状态进行取证调查。
// Reconstruct a case's state as of a specific historical timestamp (time-travel).
// Useful for forensic investigation: "What did case X look like on date Y?"
//
// Unlike the other snapshots, this query intentionally has NO TimeGenerated filter
// because it needs to scan all history back to the case's creation.
//
// Replace these parameters with your target case and desired point in time:
let targetCaseId = '<replace-with-case-id>';
// Example: datetime(2026-05-13T14:30:00Z)
let snapshotTime = datetime('<replace-with-datetime>');
//
// ============ STEP 1: Exclude cases deleted before snapshot time ============
let deletedCases = SecurityCaseEvent
| where EntityType == 'Case'
| where EventTime <= snapshotTime
| where IsDeleted == true
| distinct EntityId;
let ChangedCaseIds = SecurityCaseEvent
| where EntityType == 'Case'
| where EntityId == targetCaseId
| where EntityId !in (deletedCases)
| distinct CaseId = EntityId;
//
// ============ STEP 2: Reconstruct case properties as of snapshotTime ============
let CaseSnapshot = SecurityCaseEvent
| where EntityType == 'Case'
| where IsDeleted == false
| where EntityId in (ChangedCaseIds)
| where OperationName in ('Create', 'Update')
| where EventTime <= snapshotTime
| mv-expand PropertyNames, NewValues
| extend PropName = tostring(PropertyNames), PropValue = tostring(NewValues)
// arg_max: for each property, keep the latest value that occurred BEFORE snapshotTime
| summarize arg_max(EventTime, PropValue, EntityCreatedTime) by EntityId, PropName
| summarize
DisplayName = take_anyif(PropValue, PropName == 'displayName'),
StatusName = take_anyif(PropValue, PropName == 'caseStatus.statusName'),
TopLevelStatus = take_anyif(PropValue, PropName == 'caseStatus.topLevelStatusName'),
Severity = take_anyif(PropValue, PropName == 'severity'), // Incident cases
Priority = take_anyif(PropValue, PropName == 'priority'), // Default cases
AssignedTo = take_anyif(PropValue, PropName == 'assignedTo'),
Classification = take_anyif(PropValue, PropName == 'classification'),
Determination = take_anyif(PropValue, PropName == 'determination'),
Description = take_anyif(PropValue, PropName == 'description'),
CaseType = take_anyif(PropValue, PropName == 'caseType'),
CreatedTime = take_anyif(PropValue, PropName == 'createdTime'),
EntityCreatedTime = take_any(EntityCreatedTime),
CustomFields = take_anyif(PropValue, PropName == 'customFields'),
ClosingNotes = take_anyif(PropValue, PropName == 'closingNotes'),
SlaAssignmentStatus = take_anyif(PropValue, PropName == 'sla.assignmentStatus'),
SlaResolutionStatus = take_anyif(PropValue, PropName == 'sla.resolutionStatus'),
SlaPolicyName = take_anyif(PropValue, PropName == 'sla.policyName'),
SlaPolicyId = take_anyif(PropValue, PropName == 'sla.policyId'),
SlaPolicyAppliedDateTime = take_anyif(PropValue, PropName == 'sla.policyAppliedDateTime')
by EntityId;
//
// ============ STEP 3: Reconstruct child entities as of snapshotTime ============
// --- Tasks ---
let ActiveTasks = SecurityCaseEvent
| where EntityType == 'CaseTask'
| where ParentEntityId in (ChangedCaseIds)
| where EventTime <= snapshotTime
| summarize arg_max(EventTime, IsDeleted, OperationName) by EntityId
| where IsDeleted == false and OperationName != 'Delete'
| project TaskId = EntityId;
let TasksJson = SecurityCaseEvent
| where EntityType == 'CaseTask'
| where EntityId in (ActiveTasks)
| where OperationName in ('Create', 'Update')
| where EventTime <= snapshotTime
| mv-expand PropertyNames, NewValues
| extend PropName = tostring(PropertyNames), PropValue = tostring(NewValues)
| summarize arg_max(EventTime, PropValue, EntityCreatedTime) by EntityId, ParentEntityId, PropName
| summarize TaskProps = make_bag(pack(PropName, PropValue)), EntityCreatedTime = take_any(EntityCreatedTime) by TaskId = EntityId, CaseId = ParentEntityId
| extend Task = bag_merge(TaskProps, bag_pack('taskId', TaskId, 'entityCreatedTime', tostring(EntityCreatedTime)))
| summarize Tasks = make_list(Task) by EntityId = CaseId;
// --- Comments ---
let ActiveComments = SecurityCaseEvent
| where EntityType == 'CaseComment'
| where ParentEntityId in (ChangedCaseIds)
| where EventTime <= snapshotTime
| summarize arg_max(EventTime, IsDeleted, OperationName) by EntityId
| where IsDeleted == false and OperationName != 'Delete'
| project CommentId = EntityId;
let CommentsJson = SecurityCaseEvent
| where EntityType == 'CaseComment'
| where EntityId in (ActiveComments)
| where OperationName in ('Create', 'Update')
| where EventTime <= snapshotTime
| mv-expand PropertyNames, NewValues
| extend PropName = tostring(PropertyNames), PropValue = tostring(NewValues)
| summarize arg_max(EventTime, PropValue, EntityCreatedTime) by EntityId, ParentEntityId, PropName
| summarize CommentProps = make_bag(pack(PropName, PropValue)), EntityCreatedTime = take_any(EntityCreatedTime) by CommentId = EntityId, CaseId = ParentEntityId
| extend Comment = bag_merge(CommentProps, bag_pack('commentId', CommentId, 'entityCreatedTime', tostring(EntityCreatedTime)))
| summarize Comments = make_list(Comment) by EntityId = CaseId;
// --- Attachments ---
let ActiveAttachments = SecurityCaseEvent
| where EntityType == 'CaseAttachment'
| where ParentEntityId in (ChangedCaseIds)
| where EventTime <= snapshotTime
| summarize arg_max(EventTime, IsDeleted, OperationName) by EntityId
| where IsDeleted == false and OperationName != 'Delete'
| project AttachmentId = EntityId;
let AttachmentsJson = SecurityCaseEvent
| where EntityType == 'CaseAttachment'
| where EntityId in (ActiveAttachments)
| where OperationName in ('Create', 'Update')
| where EventTime <= snapshotTime
| mv-expand PropertyNames, NewValues
| extend PropName = tostring(PropertyNames), PropValue = tostring(NewValues)
| summarize arg_max(EventTime, PropValue, EntityCreatedTime) by EntityId, ParentEntityId, PropName
| summarize AttachmentProps = make_bag(pack(PropName, PropValue)), EntityCreatedTime = take_any(EntityCreatedTime) by AttachmentId = EntityId, CaseId = ParentEntityId
| extend Attachment = bag_merge(AttachmentProps, bag_pack('attachmentId', AttachmentId, 'entityCreatedTime', tostring(EntityCreatedTime)))
| summarize Attachments = make_list(Attachment) by EntityId = CaseId;
// --- Tags ---
let CaseTags = SecurityCaseEvent
| where EntityType == 'Case'
| where EntityId in (ChangedCaseIds)
| where OperationName in ('Create', 'Update')
| where EventTime <= snapshotTime
| where PropertyNames has 'tags'
| extend TagIdx = array_index_of(PropertyNames, 'tags')
| extend Tags = iff(TagIdx >= 0, NewValues[TagIdx], NewValues)
| summarize arg_max(EventTime, Tags) by EntityId
| project EntityId, Tags;
// --- Relations ---
let ActiveRelations = SecurityCaseEvent
| where EntityType == 'CaseRelation'
| where ParentEntityId in (ChangedCaseIds)
| where EventTime <= snapshotTime
| summarize arg_max(EventTime, IsDeleted, OperationName) by EntityId
| where IsDeleted == false and OperationName !in ('Delete', 'Unlink')
| project RelationId = EntityId;
let RelationsJson = SecurityCaseEvent
| where EntityType == 'CaseRelation'
| where EntityId in (ActiveRelations)
| where OperationName in ('Create', 'Update', 'Link')
| where EventTime <= snapshotTime
| mv-expand PropertyNames, NewValues
| extend PropName = tostring(PropertyNames), PropValue = tostring(NewValues)
| summarize arg_max(EventTime, PropValue, EntityCreatedTime) by EntityId, ParentEntityId, PropName
| summarize RelationProps = make_bag(pack(PropName, PropValue)), EntityCreatedTime = take_any(EntityCreatedTime) by RelationId = EntityId, CaseId = ParentEntityId
| extend Relation = bag_merge(RelationProps, bag_pack('relationId', RelationId, 'entityCreatedTime', tostring(EntityCreatedTime)))
| summarize Relations = make_list(Relation) by EntityId = CaseId;
//
// ============ STEP 4: Join all pieces into final output ============
CaseSnapshot
| join kind=leftouter TasksJson on EntityId
| join kind=leftouter CommentsJson on EntityId
| join kind=leftouter AttachmentsJson on EntityId
| join kind=leftouter RelationsJson on EntityId
| join kind=leftouter CaseTags on EntityId
| project
EntityId, DisplayName, StatusName, TopLevelStatus, Severity, Priority,
AssignedTo, Classification, Determination, Description,
Tags = coalesce(Tags, dynamic([])), CaseType, CreatedTime, EntityCreatedTime, CustomFields, ClosingNotes,
SlaAssignmentStatus, SlaResolutionStatus, SlaPolicyName, SlaPolicyId, SlaPolicyAppliedDateTime,
Tasks = coalesce(Tasks, dynamic([])),
Comments = coalesce(Comments, dynamic([])),
Attachments = coalesce(Attachments, dynamic([])),
Relations = coalesce(Relations, dynamic([]))
按 SLA 状态排序的事例
查找 SLA 解析状态与特定值(例如超出、有风险)匹配的所有开放案例。
// Find all open cases where the SLA resolution status matches a specific value.
// SLA status values: Pending, At Risk, Exceeded, Met
//
// Replace the placeholder below with the desired SLA status (e.g. 'Exceeded', 'At Risk')
let slaStatus = '<replace-with-sla-status>';
// --- Exclude deleted cases ---
let deletedCases = SecurityCaseEvent
| where TimeGenerated >= ago(90d)
| where EntityType == 'Case'
| where IsDeleted == true
| distinct EntityId;
// --- Exclude closed cases ---
let closedCases = SecurityCaseEvent
| where TimeGenerated >= ago(90d)
| where EntityType == 'Case'
| where OperationName in ('Create', 'Update')
| mv-expand PropertyNames, NewValues
| extend PropName = tostring(PropertyNames), PropValue = tostring(NewValues)
| where PropName == 'caseStatus.topLevelStatusName'
| summarize arg_max(EventTime, PropValue) by EntityId
| where tolower(PropValue) == 'closed'
| distinct EntityId;
// --- Reconstruct latest SLA and case properties via pivot ---
let CaseProperties =
SecurityCaseEvent
| where TimeGenerated >= ago(90d)
| where EntityType == 'Case'
| where OperationName in ('Create', 'Update')
| where EntityId !in (deletedCases)
| where EntityId !in (closedCases)
// mv-expand: expands array properties into individual rows per property change
| mv-expand PropertyNames, NewValues
| extend PropName = tostring(PropertyNames), PropValue = tostring(NewValues)
| extend NormProp = case(
PropName == 'displayName', 'DisplayName',
PropName == 'assignedTo', 'AssignedTo',
PropName == 'caseType', 'CaseType',
PropName == 'sla.resolutionStatus', 'SlaResolutionStatus',
PropName == 'sla.assignmentStatus', 'SlaAssignmentStatus',
PropName == 'sla.policyName', 'SlaPolicyName',
'')
| where NormProp != ''
// arg_max: keeps the most recent value per case per property
| summarize arg_max(EventTime, PropValue) by EntityId, NormProp
// project before pivot to avoid unintended grouping on EventTime
| project EntityId, NormProp, PropValue
// evaluate pivot: turns rows into columns (one column per property)
| evaluate pivot(NormProp, take_any(PropValue));
// --- Filter by SLA status ---
// column_ifexists: safely accesses pivot columns that may not exist if no case has SLA data
CaseProperties
| extend
SlaResolutionStatus = tostring(column_ifexists('SlaResolutionStatus', '')),
SlaAssignmentStatus = tostring(column_ifexists('SlaAssignmentStatus', '')),
SlaPolicyName = tostring(column_ifexists('SlaPolicyName', '')),
CaseType = tostring(column_ifexists('CaseType', ''))
| where tolower(SlaResolutionStatus) == tolower(slaStatus)
//| where tolower(SlaAssignmentStatus) == tolower(slaStatus) // Uncomment to filter by assignment SLA instead
//| where CaseType == '<case-type>' // Uncomment to filter by case type
//| where AssignedTo has '<user>' // Uncomment to filter by assignee
| project EntityId, DisplayName, AssignedTo, SlaResolutionStatus, SlaAssignmentStatus, SlaPolicyName, CaseType
| order by EntityId asc