Подвыбор может помочь вам:
SELECT COUNT(*)
FROM (SELECT 1
FROM groups
WHERE groups.deleted_at IS NULL
FOR SHARE SKIP LOCKED) AS q;
Причина этого заключается в том, что запрос, который блокирует строки, должен иметь возможность идентифицировать строку, которая должна быть заблокирована из результата.
src/backend/optimizer/plan/planner.c
имеет такой код комментария:
/*
* We've got trouble if FOR [KEY] UPDATE/SHARE appears inside
* grouping, since grouping renders a reference to individual tuple
* CTIDs invalid. This is also checked at parse time, but that's
* insufficient because of rule substitution, query pullup, etc.
*/
Таким образом, можно сказать, что этого требует способ его реализации.