How to bind a variable to a queried item in SPARQL
Asked Answered
S

6

16

In this simple sparql query I get a list of subjects whose object is 42

SELECT ?v WHERE { ?v ?p 42 }

If I add ?p as a variable

SELECT ?v ?p WHERE { ?v ?p 42 }

I will get two entities per row, the subject and the predicate. What if I wanted three entities, so including the 42? Something like:

SELECT ?v ?p ?m WHERE { ?v ?p (42 as m) }
Sanctimony answered 19/11, 2009 at 4:44 Comment(2)
If 42 is really a constant, why send it forth and back? When you get rows with two elements, you can just add the third. Or is this example oversimplified and you're trying to do something more complicated?Expurgatory
@StefanoBorini SPARQL 1.0 made this a bit inconvenient, but SPARQL 1.1 includes values for just this purpose (and you can specify more than one constant value for the inline data, too). I've added an answer.Lissa
K
10

Standard SPARQL 1.0 does not really allow that. There may be some implementation-specific extensions for doing it, though.

As a workaround, if the data contains a triple with 42 as an object literal, you can do it e.g. like this:

SELECT ?v ?p ?m { ?v ?p 42, ?m FILTER(?m=42)}

which is equivalent with

 SELECT ?v ?p ?m WHERE { ?v ?p 42 . ?v ?p ?m FILTER(?m=42)}

as you can write graph patterns sharing the same subject and predicate with the comma object list notation, and the WHERE keyword is optional.

For efficiency, you want to use basic graph patterns to reduce the working triple to a smaller set and only then apply FILTER expressions to further prune the results.

Ka answered 19/11, 2009 at 10:4 Comment(2)
Just realised that this doesn't work properly - this results in selecting any Triples that have the same subject and predicate as those with the object 42 so you potentially get a load of miscellaneous triples which are irrelevant to your queryChristychristye
@RobV: True, thanks for pointing that out. I've revised the answer.Ka
S
24

Another variant is to use BIND, e.g.:

SELECT ?v ?p ?m
WHERE {
  BIND(42 AS ?m)
  ?v ?p ?m
}

The BIND statement simply adds a binding for ?m, which can then be selected for the result set.

Sparke answered 14/2, 2016 at 19:11 Comment(1)
thumb up - it works in python rdflib SPARQL implementationCoinsurance
L
15

In SPARQL 1.1, you can use VALUES for this. You would write

SELECT ?v ?p ?m WHERE {
  values ?m { 42 }
  ?v ?p ?m
}
Lissa answered 3/3, 2014 at 22:47 Comment(0)
K
10

Standard SPARQL 1.0 does not really allow that. There may be some implementation-specific extensions for doing it, though.

As a workaround, if the data contains a triple with 42 as an object literal, you can do it e.g. like this:

SELECT ?v ?p ?m { ?v ?p 42, ?m FILTER(?m=42)}

which is equivalent with

 SELECT ?v ?p ?m WHERE { ?v ?p 42 . ?v ?p ?m FILTER(?m=42)}

as you can write graph patterns sharing the same subject and predicate with the comma object list notation, and the WHERE keyword is optional.

For efficiency, you want to use basic graph patterns to reduce the working triple to a smaller set and only then apply FILTER expressions to further prune the results.

Ka answered 19/11, 2009 at 10:4 Comment(2)
Just realised that this doesn't work properly - this results in selecting any Triples that have the same subject and predicate as those with the object 42 so you potentially get a load of miscellaneous triples which are irrelevant to your queryChristychristye
@RobV: True, thanks for pointing that out. I've revised the answer.Ka
S
3

You can accomplish in two ways using BINDINGS keyword as well as FILTER

Using BINDINGS

SELECT ?v ?p ?m 
WHERE { ?v ?p ?m}
BINDINGS ?m {(42)}

Using FILTER

SELECT ?v ?p ?m
WHERE {
?v ?p ?m
FILTER (?m = 42)
}
Stichter answered 3/1, 2017 at 16:33 Comment(1)
VALUES had replaced and generalized BINDINGS in the Last Call Working Draft of SPARQL 1.1 Query LanguageHaematosis
F
1
select ?v ?p ?m where { ?v ?p ?m . FILTER( ?m = 42 ) }
Finite answered 20/11, 2009 at 11:1 Comment(5)
It would seem sensible but depending on your Triple Store and SPARQL engine it is likely to be very inefficient as a lot of SPARQL engines do FILTERs in-memory which means you'd effectively load the entire dataset (since ?v ?p ?m matches everything) and then have to FILTER over all of it for objects which are 42Christychristye
True, but any SPARQL feature can be inefficient depending on Triple Store. For example, LIMIT and OFFSET seem like sensible things, these should work fast, right? For example on AllegroGraph these are postprocessing instructions, so very slow if you have lots of data. With regards to filter, FILTER, at least on Virtuoso it's very efficient, it translates to very simple SQL query with just two WHERE conditions.Expurgatory
For a simple FILTER like this then it would translate to a simple SQL query assuming your store is SQL based. LIMIT and OFFSET are typically post-processing in any SPARQL implementation since you need to apply FILTERs and ORDER BYs before you can apply them - I would not expect them to be fast over large datasets. For such a case anyway laalto's approach is more efficient and more portable across different SPARQL implementationsChristychristye
I never took a close look at laalto's approach, it didn't look right in the beginning. But yeah, it is indeed better and would work better than mine in general case.Expurgatory
Well it did have an error in it originally until he edited it the other dayChristychristye
L
1

I know this is round-about, but I believe this is doable with a subquery.

This is a useful pattern to help you work on the query in the narrow, before you let it loose on your entire dataset:

SELECT ?v ?p ?m WHERE {
   { SELECT 42 as ?m WHERE { } }
   ?v ?p ?m .
}
Leporid answered 12/9, 2011 at 17:35 Comment(2)
Actually, there is a proposal to add to sparql 1.1 to do this more directly. If this ever gets implemented, then you should be able to use "BIND ( 42 AS ?m )" instead of the subquery. w3.org/TR/sparql11-query/#bindLeporid
Actually, the values form is even nicer, and supports multiple values: values ?m { 42 } ?v ?p ?m.Lissa

© 2022 - 2024 — McMap. All rights reserved.