WITH data_types AS (SELECT table_schema, table_name, column_name, data_type,
CASE WHEN data_type='numeric' AND numeric_precision IS NOT NULL AND numeric_scale IS NOT NULL THEN data_type || '(' || numeric_precision || ',' || numeric_scale || ')'
WHEN character_maximum_length IS NOT NULL THEN data_type || '(' || character_maximum_length || ')'
WHEN datetime_precision IS NOT NULL AND data_type<>'date' THEN data_type || '(' || datetime_precision || ')'
ELSE data_type END AS precision_spec
FROM INFORMATION_SCHEMA.columns
WHERE (table_schema, table_name) IN (SELECT table_schema, table_name
FROM INFORMATION_SCHEMA.tables WHERE table_type='BASE TABLE') AND
table_schema NOT IN (SELECT schema_name
FROM INFORMATION_SCHEMA.schemata
WHERE schema_name<>'public' AND
schema_owner='postgres' AND schema_name IS NOT NULL))
SELECT column_name, data_type, Count(*) AS number_of_columns, Count(DISTINCT precision_spec) AS number_of_different_sizes,
string_agg(table_schema ||'.'|| table_name || ' ' || precision_spec,';<br>' ORDER BY precision_spec, table_schema, table_name) AS precisions
FROM data_types AS dt
GROUP BY column_name, data_type
HAVING Count(DISTINCT precision_spec)>1
ORDER BY Count(DISTINCT precision_spec) DESC, Count(*) DESC, column_name;