The list of all the queries

The number of direct and indirect child tables (foreign keys)

Query goal: Find the number of direct and all (direct+indirect) child tables of a base table based on the foreign keys. The result may help to classify the data. If the number of direct children is small but the number of all children is large, then the table probably contains classifiers. If both the number of direct and all children is large, then the table probably contains master data. If the number of all children is small, then the table probably contains transactional data, logs, or descriptive information of main entities.
Notes about the query: The query finds transitive closure of tables. In other words it finds all possible paths between tables where it is possible to reach from one table to another based on parent-child relationships. The query assumes that these relationships have been enforced in the database by declaring foreign key (referential) constraints. The query returns information about all the base tables, even those that do not participate in any foreign key constraint as the parent. In the latter case the number would be 0.
Query type: Sofware measure (Numeric values (software measures) about the database)
Query license: MIT License
Data source: system catalog only
SQL query: Click on query to copy it

WITH RECURSIVE transitive_closure AS (
WITH foo AS (SELECT conrelid AS child, confrelid AS parent
FROM pg_constraint
WHERE contype='f')
SELECT child, parent, 1 AS distance, child || '.' || parent || '.' AS path_string
FROM foo
UNION ALL
SELECT tc.child, e.parent, tc.distance + 1,  tc.path_string || e.parent || '.' AS path_string
FROM foo e INNER JOIN transitive_closure AS tc  ON e.child = tc.parent
WHERE tc.path_string NOT LIKE '%' || e.parent || '.%')
SELECT np.nspname AS table_schema, c.relname AS table_name, Count(*) AS number_of_all_children,
(SELECT Count(*) AS cnt FROM pg_constraint WHERE contype='f' AND pg_constraint.confrelid=c.oid) AS number_of_direct_children
FROM transitive_closure AS tc INNER JOIN pg_class AS c ON tc.parent=c.oid
INNER JOIN pg_namespace AS np ON c.relnamespace=np.oid
INNER JOIN pg_authid AS a ON np.nspowner=a.oid
WHERE (np.nspname='public' OR rolname<>'postgres')
GROUP BY c.oid, np.nspname, c.relname
UNION SELECT nc.nspname AS table_schema, c.relname AS table_name, 0 AS number_of_all_children, 0 AS number_of_direct_children
FROM pg_class AS c INNER JOIN pg_namespace AS nc ON c.relnamespace=nc.oid
INNER JOIN pg_authid AS a ON nc.nspowner=a.oid
WHERE (nc.nspname='public' OR rolname<>'postgres')
AND c.relkind='r'
AND NOT EXISTS (SELECT *
FROM pg_constraint
WHERE contype='f'
AND pg_constraint.confrelid=c.oid)
ORDER BY number_of_all_children DESC, table_schema, table_name;

Collections where the query belongs to

Collection nameCollection description
Find problems by overviewQueries that results point to different aspects of database that might have problems. A human reviewer has to decide based on the results as to whether there are problems or not .
Find quick numeric overview of the databaseQueries that return numeric values showing mostly the number of different types of database objects in the database

Categories where the query belongs to

Category nameCategory description
Relationships between tablesQueries of this category provide information about how database tables are connected to each other and whether such connections have been explicitly defined and whether it has been done correctly.

The list of all the queries