So, an interesting request came across my desk earlier today, to query every asset a user has ever been assigned.
Normally- I would say this should be an easy request… Query sys_audit where tablename=alm_asset, fieldname=assigned_to, filter by the values… and build a report based on this data.
However- data in sys_audit, stays forever, for every single table. So, if you attempt to run that query on any service-now instance that has been up for a few years, You will notice, it crashes.
This is because neither fieldname, nor tablename are indexed columns (on the underlying database)
However- if you look at an asset, and select history, this data is being pulled from sys_audit.
You may ask, well- why does that work when I cannot query the table at all??
The answer is- sys_audit.documentkey is an indexed field. So- when the related query looks for sys_audit where document_key = sys_id of the alm_asset, it returns very quickly, because it is indexed.
Now that we have gotten that part out of the way…. What about the report?
Well- while I am very knowledgeable on the BACKEND of service-now, and its available APIs, I do not know enough knowledge to build the query within service-now. BUT- I did create the logic in c# using a service-now library which I have created.
If you are a experienced service-now individual, you may be able to build a report based on my logic.
var Users = sn.OfType<sys_user>().Where(o => (Insert lamba expression here to locate the specific users)).ToList();
foreach (var rec in sn.OfType<alm_asset>())
{
var history = sn.OfType<sys_audit>()
.Where(o => o.documentkey == (object)rec.sys_id)
.Where(o => o.fieldname == nameof(alm_asset.assigned_to) || o.fieldname == nameof(alm_asset.u_custom_assigned_to))
//Force query to list.
.ToList()
//Local Expression
.Where(o => Users.Any(usr => usr.sys_id.Equals(o.newvalue)));
foreach (var match in history)
{
//Do Something with you results.
}
}
The above query is quite inefficient, because it pulls down ALL assigned_to history change records for every asset to evaluate locally. However- it is many times faster then attempting to query sys_audit directly.
sys_history only contains 28 days of data, before any mentions it.
Summary:
- Query all assets
- For each asset, query sys_audit where documentkey = asset.sys_id
- Perform additional filtering on sys_audit, for specific field names, or values.
- Profit.
Edit- as a last note, this could easily be implement in service-now javascript.