Запросы, которые получают первое место за что-то, действительно сложны в SPARQL, и в действительности нет отличного способа сделать это. Это почти всегда доходит до какого-то странного взлома. Во-первых, данные с объявлением префикса:
@prefix : <urn:ex:>
:p1 :has_position 1 .
:p2 :has_position 2 .
:p3 :has_position 3 .
:p4 :has_position 4 .
Тогда запрос. Строка имеет длинную конкатенацию строк, но это просто, чтобы снять префиксы, подобные описанным в вопросе. «Взлом» в этом случае означает, что две ближайшие точки q и r свести к минимуму количество | p − q | + | p − r |, поэтому мы можем вычислить это количество и принять значения q и r, которые дали его нам. Кроме того, вы должны убедиться, что вы навязываете некоторый порядок на д и г, иначе вы получите дублированные результаты (так как вы можете просто поменять д и г).
prefix : <urn:ex:>
select ?p (concat(strafter(str(?q),str(:)),", ",strafter(str(?r),str(:))) as ?neighbors) {
?p :has_position ?pos1 .
?q :has_position ?pos2 .
?r :has_position ?pos3 .
filter(?p != ?q && ?p != ?r)
filter(str(?q) < str(?r))
filter not exists {
?qq :has_position ?pos22 .
?rr :has_position ?pos33 .
filter(?p != ?qq && ?p != ?rr)
filter(str(?qq) < str(?rr))
filter((abs(?pos1 - ?pos22) + abs(?pos1 - ?pos33)) <
(abs(?pos1 - ?pos2) + abs(?pos1 - ?pos3)))
}
}
-------------------
| p | neighbors |
===================
| :p1 | "p2, p3" |
| :p2 | "p1, p3" |
| :p3 | "p2, p4" |
| :p4 | "p2, p3" |
-------------------
Теперь, вы также можете сделать это с помощью подзапроса, который находит минимальное количество для каждого р, а затем, во внешнем запросе, находит Q и г ценности, которые производят его:
prefix : <urn:ex:>
select ?p (concat(strafter(str(?q), str(:)), ", ", strafter(str(?r), str(:))) as ?neighbors) {
{ select ?p (min(abs(?pos1 - ?pos2) + abs(?pos1 - ?pos3)) as ?d) {
?p :has_position ?pos1 .
?q :has_position ?pos2 .
?r :has_position ?pos3 .
filter(?p != ?q && ?p != ?r)
filter(str(?q) < str(?r))
}
group by ?p
}
?p :has_position ?pos1 .
?q :has_position ?pos2 .
?r :has_position ?pos3 .
filter(?p != ?q && ?p != ?r)
filter(str(?q) < str(?r))
filter(abs(?pos1 - ?pos2) + abs(?pos1 - ?pos3) = ?d)
}
-------------------
| p | neighbors |
===================
| :p1 | "p2, p3" |
| :p2 | "p1, p3" |
| :p3 | "p2, p4" |
| :p4 | "p2, p3" |
-------------------
Для этого вам, вероятно, понадобится подзаголовок с заказом и лимитом. Получение первой позиции для каждого элемента сложнее в SPARQL, но этот случай должен быть возможен. –
Я попытался также это \t 'ВЫБОР ТОЧКИ СОСЕД \t ГДЕ { \t \t idPoint RDFS:?? Метка POINT. FILTER (? IdNEIGHBOR! =? IdPoint) \t \t? IdPoint: has_position? POS. \t \t { \t \t \t ВЫБОР СОСЕД \t \t \t ГДЕ { \t \t \t \t idNEIGHBOR RDFS:? Этикетка СОСЕД. \t \t \t \t? IdNEIGHBOR: has_position? POSNEIGHBOR. \t \t \t} \t \t \t ORDER BY? POINT абс (? POS-? POSNEIGHBOR) \t \t \t LIMIT 2 \t \t \t} \t} ' Но результат пуст –
я буду сделайте снимок чуть позже, но в то же время посмотрите на http://stackoverflow.com/questions/27061096/sparql-using-subquery-with-limit и некоторые другие вопросы, на которые он ссылается (см. комментарии). –