
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-26-2021 09:12 AM
ServiceNow has created numerous duplicated records in Serial table where Serial number + Serial type + CI (combined) are the same. We need to retain the latest record and remove the rest of the duplicated records. For instance in this chart, we want to keep the records in row 1 and 7, and remove the rest.
we will need 2 scripts, the first one to identify the dups and prints the records so we can analyze the data and the second one is to delete them. Please advise if you can provide the scripts to us.
Thank you very much for your help,
bk
Solved! Go to Solution.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-05-2021 11:24 AM
Thank you Rahul for the script. I also got another script from a former colleague that works too. Here is the script:
// *********************************** SETUP ****************************************************************************************************************
var dryRun = true; // SET THIS TO FALSE TO ACTUALLY DELETE RECORDS
var tableName = 'cmdb_serial_number'; // TARGET TABLE
var encodedQuery = ‘cmdb_ci'=; // APPLY ANY FILTER CONDITIONS HERE
var identifierFields = cmdb_ci.name='XXXXXXX’; //USED TO IDENTIFY THE DUPLICATES
var batch = 100; //SETS THE LIMIT FOR HOW MANY RECORDS ARE IN THE GLIDERECORD
// **********************************************************************************************************************************************************
var identifiers = identifierFields.split(','); //split up the groupby fields, we'll use this one later
var agg = new GlideAggregate(tableName);
agg.addQuery(encodedQuery);
agg.setLimit(batch);
// ADD THE COMBINATION OF UNIQUE IDENTIFIERS HERE
for(var i = 0; i < identifiers.length; i++) {
agg.groupBy(identifiers[i]);
}
// DON'T BOTHER READING ANY RECORDS THAT AREN'T DUPLICATE
agg.addAggregate('COUNT');
agg.addHaving('COUNT','>','1'); // only where 1 or more duplicates exist
agg.query();
// AT THIS POINT WE ONLY HAVE DUPLICATE RECORDSETS (WHERE THERE IS MORE THAN ONE RECORD WITH THE SAME IDENTIFYING FIELDS)
// NOW LOOP THROUGH ALL OF THOSE RECORDSETS, KEEPING ONLY THE OLDEST RECORD AND DELETING THE REST
var resultString = '\nUnique Set\tRecord to keep\tRecord(s) to delete\n'; // In order to avoid using many gs.print() statements we simply add all the results to a string and display them at the end.
var resultCount = 0; //Count the duplicates
while(agg.next()) {
resultString += getSetDetailsString(agg); //log the set that brought us here
var dup = new GlideRecord(tableName);
dup.addQuery(encodedQuery);
dup.setLimit(batch);
//get the records that match the set
for(var i = 0; i < identifiers.length; i++) {
dup.addQuery(identifiers[i],agg[identifiers[i]]);
}
// order by date ascending. the first record is the oldest and the one we want to preserve. Change for 'orderByDesc' to preserve the newest record and remove the rest
dup.orderBy('sys_created_on');
dup.query();
// skip the first record (original) and log it
dup.next();
resultString += (dup.sys_created_on + ' - '+ dup.sys_id + '\t');
// loop through and delete the remaining records for this set. Only deletes if dryRun = false
while(dup.next()) {
resultString += (dup.sys_created_on + ' - '+ dup.sys_id + ', ');
resultCount++;
if(!dryRun) { //CAREFUL
dup.setWorkflow(false);
dup.deleteRecord();
}
}
resultString += '\n';
}
//Display results in TAB SEPARATED FORMAT
gs.print('Duplicate count: ' + resultCount);
gs.print(resultString);
//helper method to dynamically create the SET string for logging
function getSetDetailsString(gRecord) {
var returnString = '(';
for(var i = 0; i < identifiers.length; i++) {
returnString += identifiers[i] + ': ' + gRecord[identifiers[i]] + ', ';
}
returnString += ')\t';
return returnString;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-26-2021 10:49 AM
https://community.servicenow.com/community?id=community_question&sys_id=39868725db1cdbc01dcaf3231f9619c8

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-27-2021 11:38 PM
You can first identify the duplicates using below Script. Once its identified you can easily delete them.
Find Duplicate CIs by Serial Number
gs.print(getDuplicates('cmdb_ci_server','serial_number'));
function getDuplicates(tablename,val) {
var dupRecords = [];
var gaDupCheck = new GlideAggregate(tablename);
gaDupCheck.addQuery('active','true');
gaDupCheck.addAggregate('COUNT',val);
gaDupCheck.addNotNullQuery(val);
gaDupCheck.groupBy(val);
gaDupCheck.addHaving('COUNT', '>', 1);
gaDupCheck.query();
while (gaDupCheck.next()) {
dupRecords.push(gaDupCheck[val].toString());
}
return dupRecords;
}
You can customize it as per need.
Now for Deletion Mark any Field in above table as DeleteFlag = Yes
Then you can query all these records where Delete=Yes and delete it .
var snnod = new GlideRecord('cmdb_ci_server'); //Table Name
snnod.addQuery("deleteflag","true"); // Filter
snnod.query();
while(snnod.next()){
snnod.setWorkflow(false);
count++;
snnod.deleteRecord(); // Delete records
}
gs.print('No. of records deleted = '+count);
Hope this helps.
Regards
RP

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-08-2021 08:13 AM
Hi Rahul,
Thank you for the script. Unfortunately this script will identify all "legit" and "not legit" duplicates in Serial number table. Legit duplicates are that the same serial numbers having different serial number types (uuid, chassis, physical etc). Non legit dups in Serial number table are those that we have multiple records for the same serial number that have the same serial type.
for instance in my examples above, Serial abc123 is duplicated only if the type is also the same.
So Serial abc123 with serial type of Chassis is not considered a duplicate with Serial = abc123 and type = system. They both can and should exist.
Unfortunately I am not experienced in scripting but I would like to modify your scrip to implement this logic to find only the "not legit" duplicates where serial number and serial number type (combined) are duplicated.
Thank you
bk

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-08-2021 07:21 PM
what is the volume you have in Serial No Table?
You can export records in XLS (with Sys_Id column) and then Play with data in XLS.
now fetch the records from XLS .
Fire the Query based on SYS_ID on Serial No Table - SYS_ID is oneof (YOUR LIST).
Then you can delete from GUI.
Regards
RP