public ArrayList<DuplicateMusicObject> executeSQLDuplicates(String sql, String keyColumn,String duplicateTitle) throws SQLException {
		
		HashMap<String,DuplicateMusicObject> retVal = new HashMap<String,DuplicateMusicObject>();
		
		Statement stmt = null;
		ResultSet rs = null;
		
		try {
			
			if (connection == null) {
				connection = getConnection();
			}
			
			/*
			String sql = "select n1.id, n1.song_name,n1.file_name,n1.folder_path,n1.file_hash,n1.file_size,n1.album,n1.artist,n1.song_year,n1.modified, n2.id as ID2, n2.song_name as NAME2 FROM "+
					     "org.music n1 join org.music n2 "+
					     "on RTRIM(LTRIM(UCASE(n1.song_name))) = RTRIM(LTRIM(UCASE(n2.song_name))) "+
					     "AND NOT n1.id IS NULL "+
					     "AND NOT n2.id IS NULL "+
					     "AND NOT n1.id = n2.id ";
					    // "ORDER BY n1.song_name";
			*/
			stmt = connection.createStatement();			
			
			log.info("Running: " + sql);
			
			long startTime = System.currentTimeMillis();
			
			rs = stmt.executeQuery(sql);
			
			log.info("Executed " + (System.currentTimeMillis()-startTime));
			
			DuplicateMusicObject currentMusicObject = null;
			
			HashSet<Integer> processed = new HashSet<Integer>();
			
			long rows = 0;
			long startRowTime = System.currentTimeMillis();
			long processTime = System.currentTimeMillis();
			
			while (rs.next()) {

				if (!processed.contains(rs.getInt("id"))) {
				
					processed.add(rs.getInt("id"));
					
					rows++;
	
					MusicObject match = populateMusic(rs);
					
					if (retVal.containsKey(rs.getString(keyColumn))) {
						currentMusicObject = retVal.remove(rs.getString(keyColumn));
					} else {
						currentMusicObject = new DuplicateMusicObject();
						currentMusicObject.setDuplicateCriteria(duplicateTitle +" " + rs.getString(keyColumn));
					}
					
					currentMusicObject.addID(match);
						
					retVal.put(rs.getString(keyColumn), currentMusicObject);
					
					if (rows%10 == 0) {
						log.info("Up to row " + rows+". To process this many rows took around " + ((System.currentTimeMillis()-startRowTime)/1000f) + " seconds.");
						startRowTime = System.currentTimeMillis();
						// Row processing time = total time to read the next row from the database, make sure it's unique, and process it.
					}
					
					} else {
	//					log.info("Skipped " + rs.getInt("id"));
					}
			}		
			
			log.info("Rows processed: " + rows);
			long finalProcessTime = System.currentTimeMillis()-processTime;
			log.info("Process time : " + (finalProcessTime/1000) + "seconds or " + (finalProcessTime/60/1000) + " minutes");
			
		} finally {
			close(rs,stmt);
		}
		
		return new ArrayList<DuplicateMusicObject>(retVal.values());
	}