Как привязать переменную к запрашиваемому элементу в SPARQL

В этом простом запросе sparql я получаю список субъектов, объект которых равен 42.

SELECT ?v WHERE { ?v ?p 42 }

Если я добавлю ?p в качестве переменной

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

Я буду получать по две сущности в строке: подлежащее и предикат. Что, если мне нужно три сущности, включая 42? Что-то вроде:

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

person Stefano Borini    schedule 19.11.2009    source источник
comment
Если 42 действительно константа, зачем посылать ее вперед и назад? Когда вы получаете строки с двумя элементами, вы можете просто добавить третий. Или этот пример слишком упрощен, и вы пытаетесь сделать что-то более сложное?   -  person Pēteris Caune    schedule 19.11.2009
comment
@StefanoBorini SPARQL 1.0 сделал это немного неудобным, но SPARQL 1.1 включает values только для этой цели (и вы также можете указать более одного постоянного значения для встроенных данных). Я добавил ответ.   -  person Joshua Taylor    schedule 04.03.2014


Ответы (6)


Стандартный SPARQL 1.0 не позволяет этого. Однако для этого могут быть некоторые специфичные для реализации расширения.

В качестве обходного пути, если данные содержат тройку с 42 в качестве литерала объекта, вы можете сделать это, например. как это:

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

что эквивалентно

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

так как вы можете писать шаблоны графов, использующие один и тот же субъект и предикат с нотацией списка объектов с запятыми, а ключевое слово WHERE является необязательным.

Для повышения эффективности вы хотите использовать базовые шаблоны графов, чтобы уменьшить рабочую тройку до меньшего набора, и только затем применять выражения FILTER для дальнейшего сокращения результатов.

person laalto    schedule 19.11.2009
comment
Только что понял, что это не работает должным образом - это приводит к выбору любых троек, которые имеют тот же субъект и предикат, что и те, у которых есть объект 42, поэтому вы потенциально можете получить множество разных троек, которые не имеют отношения к вашему запросу. - person RobV; 07.12.2009
comment
@RobV: Верно, спасибо, что указали на это. Я пересмотрел ответ. - person laalto; 07.12.2009

Другой вариант - использовать BIND, например:

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

Оператор BIND просто добавляет привязку для ?m, которую затем можно выбрать для результирующего набора.

person scotthenninger    schedule 14.02.2016
comment
большой палец вверх - это работает в реализации python rdflib SPARQL - person lowtech; 15.08.2017

В SPARQL 1.1 для этого можно использовать VALUES. Вы бы написали

SELECT ?v ?p ?m WHERE {
  values ?m { 42 }
  ?v ?p ?m
}
person Joshua Taylor    schedule 03.03.2014

Вы можете сделать это двумя способами, используя ключевое слово BINDINGS, а также FILTER.

Использование ПРИВЯЗОК

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

Использование ФИЛЬТРА

SELECT ?v ?p ?m
WHERE {
?v ?p ?m
FILTER (?m = 42)
}
person Omar Chaudhry    schedule 03.01.2017
comment
VALUES заменил и обобщил BINDINGS в последнем Вызов рабочего проекта языка запросов SPARQL 1.1 - person Stanislav Kralin; 31.07.2017

Я знаю, что это обходной путь, но я считаю, что это выполнимо с помощью подзапроса.

Это полезный шаблон, который поможет вам работать над запросом в узком кругу, прежде чем вы позволите ему работать со всем набором данных:

SELECT ?v ?p ?m WHERE {
   { SELECT 42 as ?m WHERE { } }
   ?v ?p ?m .
}
person Doug Whitehead    schedule 12.09.2011
comment
Собственно, есть предложение добавить в sparql 1.1, чтобы сделать это более непосредственно. Если это когда-нибудь будет реализовано, вы сможете использовать BIND ( 42 AS ?m ) вместо подзапроса. w3.org/TR/sparql11-query/#bind - person Doug Whitehead; 13.09.2011
comment
На самом деле форма values даже лучше и поддерживает несколько значений: values ?m { 42 } ?v ?p ?m. - person Joshua Taylor; 03.06.2015

person    schedule
comment
Это может показаться разумным, но в зависимости от вашего Triple Store и механизма SPARQL это, вероятно, будет очень неэффективным, поскольку многие механизмы SPARQL выполняют ФИЛЬТРЫ в памяти, что означает, что вы эффективно загрузите весь набор данных (поскольку ?v ?p ?m соответствует все), а затем нужно ФИЛЬТРОВАТЬ все это для объектов, которые 42 - person RobV; 07.12.2009
comment
Верно, но любая функция SPARQL может быть неэффективной в зависимости от Triple Store. Например, LIMIT и OFFSET кажутся разумными вещами, они должны работать быстро, верно? Например, в AllegroGraph это инструкции по постобработке, поэтому они очень медленные, если у вас много данных. Что касается фильтра FILTER, по крайней мере, на Virtuoso он очень эффективен, он преобразуется в очень простой SQL-запрос всего с двумя условиями WHERE. - person Pēteris Caune; 07.12.2009
comment
Для такого простого ФИЛЬТРА он будет преобразован в простой SQL-запрос, предполагая, что ваш магазин основан на SQL. LIMIT и OFFSET обычно являются постобработкой в ​​любой реализации SPARQL, поскольку вам нужно применить FILTER и ORDER BY, прежде чем вы сможете их применить — я бы не ожидал, что они будут быстрыми для больших наборов данных. В любом случае для такого случая подход laalto более эффективен и более переносим в разные реализации SPARQL. - person RobV; 08.12.2009
comment
Я никогда не присматривался к подходу Лаалто, с самого начала он выглядел неправильно. Но да, это действительно лучше, и в общем случае будет работать лучше, чем у меня. - person Pēteris Caune; 08.12.2009
comment
Ну, изначально в нем была ошибка, пока он не отредактировал его на днях. - person RobV; 08.12.2009