WITH parameters_grouped AS (SELECT p.specific_schema AS routine_schema,
regexp_replace(p.specific_name,'_[0-9]*$','') AS routine_name,
(SELECT r.routine_type FROM information_schema.routines AS r WHERE r.specific_schema=p.specific_schema AND r.specific_name=p.specific_name) AS routine_type,
pg_get_function_identity_arguments(translate(substring(p.specific_name,'_[0-9]+$'),'_','')::int::oid) AS parameters,
string_agg(p.parameter_name || ' ' || p.data_type || ' ' || p.parameter_mode, ', ' ORDER BY parameter_name, parameter_mode) AS parameters_normalized
FROM
information_schema.parameters AS p
WHERE specific_schema NOT IN (SELECT schema_name
FROM INFORMATION_SCHEMA.schemata
WHERE schema_name<>'public' AND
schema_owner='postgres' AND schema_name IS NOT NULL)
AND NOT EXISTS (SELECT 1
FROM pg_catalog.pg_depend d inner join pg_catalog.pg_proc pc ON d.objid=pc.oid
WHERE EXISTS (SELECT 1 FROM pg_catalog.pg_extension e WHERE d.refobjid=e.oid) AND
pc.proname || '_' || pc.oid = p.specific_name)
GROUP BY p.specific_schema, p.specific_name, parameters, routine_type)
SELECT parameters_normalized, Count(*) AS number_of_occurrences,
string_agg(routine_type || ' ' || routine_schema || '.' || routine_name || '(' || parameters || ')', ';<br>' ORDER BY routine_schema, routine_name, parameters) AS routines
FROM parameters_grouped
GROUP BY parameters_normalized
HAVING Count(*)>1
ORDER BY Count(*) DESC, parameters_normalized;