Skip to content

Commit ee88421

Browse files
authored
Create findDuplicatesByCombination.js
1 parent bb022ba commit ee88421

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/**
2+
* Finds and reports records that have duplicate values across a combination of specified fields instead of a single field
3+
* Useful for finding for example duplicate items where unique key is not just 1 field
4+
*/
5+
6+
// --- UPDATE ONLY THE VALUES BELOW ---
7+
var tableName = 'cmdb_model'; // ADD: The table you want to check for duplicates.
8+
var fieldNames = ['name', 'model_number', 'manufacturer']; // ADD: An array of fields that create the unique combination.
9+
10+
// --- DO NOT EDIT BELOW THIS LINE ---
11+
findDuplicateCombinations(tableName, fieldNames);
12+
13+
function findDuplicateCombinations(tableName, fieldNames) {
14+
/**************************************/
15+
/*** Basic Error Handling ***/
16+
/**************************************/
17+
18+
// Check if the table exists
19+
if (!gs.tableExists(tableName)) {
20+
gs.print('Error: Table "' + tableName + '" does not exist.');
21+
return;
22+
}
23+
24+
// Check if fieldNames is a valid, non-empty array
25+
if (!Array.isArray(fieldNames) || fieldNames.length === 0) {
26+
gs.print('Error: The "fieldNames" variable must be an array with at least one field.');
27+
return;
28+
}
29+
30+
// Check if all specified fields exist on the table
31+
var gr = new GlideRecord(tableName);
32+
gr.initialize();
33+
for (var i = 0; i < fieldNames.length; i++) {
34+
var currentField = fieldNames[i];
35+
if (!gr.isValidField(currentField)) {
36+
gs.print('Error: The field "' + currentField + '" does not exist on the "' + tableName + '" table.');
37+
return;
38+
}
39+
}
40+
41+
/***************************************/
42+
/*** Find Duplicate Combinations ***/
43+
/***************************************/
44+
var duplicateJson = {}; // Stores the duplicate records and their counts
45+
var duplicateGroupCount = 0; // Counts the number of groups of duplicates
46+
47+
var duplicateAggregate = new GlideAggregate(tableName);
48+
duplicateAggregate.addAggregate('COUNT');
49+
50+
// Loop through the array to group by each field, creating the combination
51+
for (var j = 0; j < fieldNames.length; j++) {
52+
var field = fieldNames[j];
53+
duplicateAggregate.groupBy(field);
54+
duplicateAggregate.addNotNullQuery(field); // Ignore records where any part of the combination is empty
55+
}
56+
57+
duplicateAggregate.addHaving('COUNT', '>', 1); // More than 1 means it is a duplicate combination
58+
duplicateAggregate.query();
59+
60+
while (duplicateAggregate.next()) {
61+
duplicateGroupCount++;
62+
var combinationDisplay = [];
63+
64+
for (var k = 0; k < fieldNames.length; k++) {
65+
var fieldName = fieldNames[k];
66+
var fieldValue = duplicateAggregate.getDisplayValue(fieldName) || duplicateAggregate.getValue(fieldName);
67+
combinationDisplay.push(fieldName + ': "' + fieldValue + '"');
68+
}
69+
70+
var displayKey = combinationDisplay.join(', ');
71+
var countInGroup = duplicateAggregate.getAggregate('COUNT');
72+
duplicateJson[displayKey] = countInGroup;
73+
}
74+
75+
/***************************************/
76+
/*** Print the Results ***/
77+
/***************************************/
78+
79+
// No duplicates found
80+
var fieldCombinationString = '"' + fieldNames.join('", "') + '"';
81+
if (Object.keys(duplicateJson).length === 0) {
82+
gs.print('No duplicates found for the field combination [' + fieldCombinationString + '] on table "' + tableName + '".');
83+
return;
84+
}
85+
86+
// Duplicates were found
87+
gs.print("Found " + duplicateGroupCount + " groups of duplicates based on the combination [" + fieldCombinationString + "]:");
88+
89+
for (var key in duplicateJson) {
90+
gs.print('Combination {' + key + '} has ' + duplicateJson[key] + ' occurrences.');
91+
}
92+
}

0 commit comments

Comments
 (0)