Skip to content

HAVING — filter groups ​

HAVING filters after grouping: it keeps or drops whole groups, where FILTER keeps or drops individual solutions. You can refer to an aggregate by its alias or write the aggregate again inside HAVING.

Examples use the sample data.

By alias ​

People who know more than one person:

sql
SELECT * FROM pgrdf.sparql($$
  PREFIX foaf: <http://xmlns.com/foaf/0.1/>
  SELECT ?p (COUNT(?f) AS ?friends)
  WHERE { ?p foaf:knows ?f }
  GROUP BY ?p
  HAVING(?friends > 1)
$$);
--  {"p": "http://example.org/alice", "friends": "2"}

With the aggregate inline ​

People whose friends' ages add up to more than 50:

sql
SELECT * FROM pgrdf.sparql($$
  PREFIX foaf: <http://xmlns.com/foaf/0.1/>
  PREFIX ex:   <http://example.org/>
  SELECT ?p
  WHERE { ?p foaf:knows ?f . ?f ex:age ?a }
  GROUP BY ?p
  HAVING(SUM(?a) > 50)
$$);
--  {"p": "http://example.org/alice"}

The aggregate does not have to be in the SELECT list:

sql
SELECT * FROM pgrdf.sparql($$
  SELECT ?s (COUNT(*) AS ?n)
  WHERE { ?s ?p ?o }
  GROUP BY ?s
  HAVING(COUNT(*) >= 5)
$$);
--  {"n": "6", "s": "http://example.org/alice"}

Averages ​

sql
SELECT * FROM pgrdf.sparql($$
  PREFIX foaf: <http://xmlns.com/foaf/0.1/>
  PREFIX ex:   <http://example.org/>
  SELECT ?p (AVG(?age) AS ?avgFriendAge)
  WHERE { ?p foaf:knows ?f . ?f ex:age ?age }
  GROUP BY ?p
  HAVING(AVG(?age) > 30)
$$);
--  {"p": "http://example.org/alice", "avgFriendAge": "35.0000000000000000"}

HAVING accepts the same operators and functions as FILTER; an expression outside that list is refused with 0A000.

pgRDF is released under the MIT license. Documentation built with VitePress, served via GitHub Pages.