Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/**
* Finds and reports records that have duplicate values across a combination of specified fields instead of a single field
* Useful for finding for example duplicate items where unique key is not just 1 field
*/

// --- UPDATE ONLY THE VALUES BELOW ---
var tableName = 'cmdb_model'; // ADD: The table you want to check for duplicates.
var fieldNames = ['name', 'model_number', 'manufacturer']; // ADD: An array of fields that create the unique combination.

// --- DO NOT EDIT BELOW THIS LINE ---
findDuplicateCombinations(tableName, fieldNames);

function findDuplicateCombinations(tableName, fieldNames) {
/**************************************/
/*** Basic Error Handling ***/
/**************************************/

// Check if the table exists
if (!gs.tableExists(tableName)) {
gs.print('Error: Table "' + tableName + '" does not exist.');
return;
}

// Check if fieldNames is a valid, non-empty array
if (!Array.isArray(fieldNames) || fieldNames.length === 0) {
gs.print('Error: The "fieldNames" variable must be an array with at least one field.');
return;
}

// Check if all specified fields exist on the table
var gr = new GlideRecord(tableName);
gr.initialize();
for (var i = 0; i < fieldNames.length; i++) {
var currentField = fieldNames[i];
if (!gr.isValidField(currentField)) {
gs.print('Error: The field "' + currentField + '" does not exist on the "' + tableName + '" table.');
return;
}
}

/***************************************/
/*** Find Duplicate Combinations ***/
/***************************************/
var duplicateJson = {}; // Stores the duplicate records and their counts
var duplicateGroupCount = 0; // Counts the number of groups of duplicates

var duplicateAggregate = new GlideAggregate(tableName);
duplicateAggregate.addAggregate('COUNT');

// Loop through the array to group by each field, creating the combination
for (var j = 0; j < fieldNames.length; j++) {
var field = fieldNames[j];
duplicateAggregate.groupBy(field);
duplicateAggregate.addNotNullQuery(field); // Ignore records where any part of the combination is empty
}

duplicateAggregate.addHaving('COUNT', '>', 1); // More than 1 means it is a duplicate combination
duplicateAggregate.query();

while (duplicateAggregate.next()) {
duplicateGroupCount++;
var combinationDisplay = [];

for (var k = 0; k < fieldNames.length; k++) {
var fieldName = fieldNames[k];
var fieldValue = duplicateAggregate.getDisplayValue(fieldName) || duplicateAggregate.getValue(fieldName);
combinationDisplay.push(fieldName + ': "' + fieldValue + '"');
}

var displayKey = combinationDisplay.join(', ');
var countInGroup = duplicateAggregate.getAggregate('COUNT');
duplicateJson[displayKey] = countInGroup;
}

/***************************************/
/*** Print the Results ***/
/***************************************/

// No duplicates found
var fieldCombinationString = '"' + fieldNames.join('", "') + '"';
if (Object.keys(duplicateJson).length === 0) {
gs.print('No duplicates found for the field combination [' + fieldCombinationString + '] on table "' + tableName + '".');
return;
}

// Duplicates were found
gs.print("Found " + duplicateGroupCount + " groups of duplicates based on the combination [" + fieldCombinationString + "]:");

for (var key in duplicateJson) {
gs.print('Combination {' + key + '} has ' + duplicateJson[key] + ' occurrences.');
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
## ServiceNow Duplicate Record Finder
A simple server-side script for ServiceNow that finds and reports on duplicate values for any field on any table. It uses an efficient GlideAggregate query and formats the results into a clean, readable report.

# ServiceNow Duplicate Record Finder
A simple server-side script for ServiceNow that finds and reports on duplicate values for any field on any table. It uses an efficient `GlideAggregate` query.
## Find Duplicates by Single Field - `findDuplicatesBySingleField.js`
This finds duplicates based on a single field which matches
### How to Use
This script is designed to be run in **Scripts - Background** or as a Fix Script.
1. Navigate: Go to **System Definition > Scripts - Background** (or type sys.scripts.do in the filter navigator).
2. Copy Script: Copy the entire contents of the script.js file.
2. Copy Script: Copy the entire contents of the `findDuplicatesBySingleField.js` file.
3. Paste and Configure: Paste the script into the "Run script" text box. Add the table to search in `tableName` and the field to search for duplicates in `fieldName`
```js
// Update ONLY below values to find duplicates
Expand All @@ -22,6 +23,25 @@ This script is designed to be run in **Scripts - Background** or as a Fix Script
var fieldName = 'short_description';
```


4. Run Script: Click the "Run script" button. The results will be displayed on the screen below the editor.

## Find Duplicates by Field Combination - `findDuplicatesByCombination.js`
This is a more powerful script that finds duplicate records based on a unique combination of one or more fields.

### How to use
This script is also designed to be run in **Scripts - Background**
1. Navigate: Go to **System Definition > Scripts - Background**
2. Copy Script: Copy the entire contents of the `findDuplicatesByCombination.js` file.
3. Paste and Configure: Paste the script into the "Run script" text box. Update the `tableName` field and the `fieldNames` array. The `fieldNames` variable is an array, so even a single field must be enclosed in square brackets `[]`

```js
// --- UPDATE ONLY THE VALUES BELOW ---
var tableName = '<table_name>'; // The table you want to check.
var fieldNames = ['field_1', 'field_2']; // An array of fields for the unique combination.
```

For example, to find models with the same name, model number and manufacturer
```js
var tableName = 'cmdb_model';
var fieldNames = ['name', 'model_number', 'manufacturer'];
```
Loading