I have a PostgreSQL database (9.2) with a table of parent-child relations. I have a query that looks for nodes having multiple parents.
The following query works and returns the correct results:
SELECT node,parents FROM
(
SELECT nr.child AS node, COUNT(nr.parent) AS parents
FROM node_relation nr
GROUP BY nr.child
) AS count WHERE parents > 1;
The result set:
node | parents
--------+---------
n21174 | 2
n8635 | 2
(2 rows)
The table definition is:
Table "public.node_relation"
Column | Type | Modifiers
-------------+-----------------------+---------------
child | character varying(50) | not null
parent | character varying(50) | not null
Indexes:
"node_relation_pkey" PRIMARY KEY, btree (child, parent)
I re-wrote the query to not use a sub-select:
SELECT child AS node, COUNT(parent) AS parents
FROM node_relation
GROUP BY child
HAVING COUNT(parent) > 1;
The new query works, but I wonder about the COUNT function being invoked multiple times.
Update: Here is the query plan:
QUERY PLAN
-------------------------------------------------------------------------------------------------------------
GroupAggregate (cost=0.00..1658.81 rows=19970 width=16)
Filter: (count(parent) > 1)
-> Index Only Scan using node_relation_pkey on node_relation (cost=0.00..1259.40 rows=19971 width=16)
I would prefer to use the parents
alias but the following does not work:
SELECT child AS node, COUNT(parent) AS parents
FROM node_relation
GROUP BY child
HAVING parents > 1;
ERROR: column "parents" does not exist
LINE 1: ...parents FROM node_relation GROUP BY child HAVING parents > ...
^
Will PostgreSQL optimize out the multiple invocations of COUNT
?
If not, is there an alternative form of this query that would be more efficient?
COUNT()
twice.HAVING
clause will re-use the same values from theSELECT
clause.. That's why it's aHAVING
(vs aWHERE
).. Yes, Postgres is smart enough to do that (as ypercube said)