plan_nodes holds the executed plans (EXPLAIN ANALYZE output) of several queries as trees: one row per operator, with parent_id pointing at the operator that consumes its output (NULL for the root). node_id is unique within a query only. est_rows is the optimizer's estimate, actual_rows what the operator really produced.
A node is misestimated when its estimate is off by a factor of 10 or more in either direction. Clamp both counts at 1 to avoid dividing by zero: with e = GREATEST(est_rows, 1) and a = GREATEST(actual_rows, 1), the node is misestimated when a >= 10 * e or e >= 10 * a.
A bad estimate propagates upward, so the node where it starts is the deepest misestimated node: the one furthest from the root (the root has depth 0). Break ties between equally deep nodes by the smaller node_id.
For each query with at least one misestimated node, return query_id, node_id, operator, depth, est_rows, actual_rows. Sort by query_id. Plans can be deeper than the ones in this sample.