Ivo Velitchkov
Ivo Velitchkov

Reputation: 2431

Exclude results which have the same property and value

If I have this data:

:a :p :x; a :C .
:b :p :y; a :C . 
:c :p :y; a :C .
:d :q :z; a :C .
:e :p :y; a :C .

How to make a SPARQL query to select the first ?s :p :y and exclude any other.

In other words, how to change this query:

SELECT *
WHERE {?s a :C}

so that on this data, there should be only two results, :d and either :b or :c or :e. It doesn't matter which, as it depends on the order of matching against the pattern, which I guess is outside the control of the query.

Note: I'm simplifying the actual case, where there is a set of patterns, not just ?s a :C, but the idea is, if some matching triples are also linked with :p, there should be one result for identical ?o in the ?s :p ?o pattern.

Upvotes: 1

Views: 619

Answers (2)

Joshua Taylor
Joshua Taylor

Reputation: 85843

You can group by ?p and ?o and then sample from the ?s values in each group:

select (sample(?s_) as ?s) ?p ?o where {
  ?s_ a :C .
  ?s_ ?p ?o. 

  #-- Filter here is used to exclude the property that was used
  #-- for selecting individuals (?s_ a :C).  In general, this 
  #-- just needs to make sure that the selection criteria aren't 
  #-- the same as what we're grouping on.  If the candidate values
  #-- of ?p are known in advance, this could replaced by 
  #-- `values ?p { :p :q ... }`.
  filter(?p != rdf:type)
}
group by ?p ?o

Upvotes: 4

evsheino
evsheino

Reputation: 2277

You can use LIMIT to limit the results to only one row:

SELECT ?s {
  ?s :p :y .
} LIMIT 1

You can use ORDER BY to affect the order of the results and thus the resource that will be selected.

Upvotes: 0

Related Questions