Вот довольно элегантное и эффективное решение:
- В подзапросе используйте
GROUP BY
с агрегатом group_concat
, чтобы объединить URI для всех жителей одного города в одну длинную строку.
- Вне подзапроса используйте строковые функции, чтобы разбить длинную строку и взять первые n элементов.
Сделано здесь для первых 100 городов по пять человек в каждом городе:
SELECT ?c ?p1 ?p2 ?p3 ?p4 ?p5 {
{
SELECT ?c (group_concat(?p; separator=' ') AS ?list1) {
{
SELECT ?c { ?c a dbo:City } LIMIT 100
}
OPTIONAL { ?p dbo:birthPlace ?c }
}
GROUP BY ?c
}
BIND (if(?list1, strAfter(?list1, ' '), undef) AS ?list2)
BIND (if(?list2, strAfter(?list2, ' '), undef) AS ?list3)
BIND (if(?list3, strAfter(?list3, ' '), undef) AS ?list4)
BIND (if(?list4, strAfter(?list4, ' '), undef) AS ?list5)
BIND (if(?list1, if(contains(?list1, ' '), IRI(strBefore(?list1, ' ')), IRI(?list1)), undef) AS ?p1)
BIND (if(?list2, if(contains(?list2, ' '), IRI(strBefore(?list2, ' ')), IRI(?list2)), undef) AS ?p2)
BIND (if(?list3, if(contains(?list3, ' '), IRI(strBefore(?list3, ' ')), IRI(?list3)), undef) AS ?p3)
BIND (if(?list4, if(contains(?list4, ' '), IRI(strBefore(?list4, ' ')), IRI(?list4)), undef) AS ?p4)
BIND (if(?list5, if(contains(?list5, ' '), IRI(strBefore(?list5, ' ')), IRI(?list5)), undef) AS ?p5)
}