#sparql
#sparql
Вопрос:
На моем графике узел категории «Файл» «Владеет» многими узлами разных категорий. Я пытаюсь получить список файлов, включая количество подключенных узлов определенных категорий.
Мой текущий лучший запрос выглядит следующим образом:
SELECT ?uuid ?fileName ?tableCount ?toCount
WHERE {
?uuid 'Category' 'File' .
?uuid 'Name' ?fileName .
{
SELECT (COUNT(*) as ?tableCount)
WHERE
{
VALUES (?category ) { ('BaseTable') }
?uuid 'Owns' ?elemUUID .
?elemUUID 'Category' ?category .
}
}
{
SELECT (COUNT(*) as ?toCount)
WHERE
{
VALUES (?category ) { ('TableOccurrence') }
?uuid 'Owns' ?elemUUID .
?elemUUID 'Category' ?category .
}
}
}
Вывод представляет собой отдельный список файлов, но подсчеты являются подсчетом для этой категории во ВСЕХ файлах (т. Е. Каждый файл имеет одинаковое значение для ?toCount , и каждый файл имеет одинаковое значение для ?tableCount ).
Очевидно, что я чего-то не понимаю в том, как работают подзапросы. Любая помощь будет с благодарностью принята.
Комментарии:
1. Оценка SPARQL выполняется снизу вверх, т.Е. Сначала Выполняются подзапросы — таким образом, они не знают о привязках внешнего запроса.
2. Хорошо, @UninformedUser… Но тогда как правильно выполнить такое накопление?
Ответ №1:
Переменные во внутренних запросах не отображаются снаружи, если они не отображаются в выборе. Вместо этого вам следует выполнить такой запрос (простите за редактирование, но это значительно упростит отслеживание и для других пользователей):
SELECT ?uuid ?fileName ?tableCount ?toCount
WHERE {
?uuid :category 'File' .
?uuid :name ?fileName .
{
SELECT ?uuid (COUNT(*) as ?tableCount)
WHERE
{
VALUES (?category ) { ('BaseTable') }
?uuid :owns ?elemUUID .
?elemUUID :category ?category .
}
GROUP BY ?uuid #This is the missing link
}
{
SELECT ?uuid (COUNT(*) as ?toCount)
WHERE
{
VALUES (?category ) { ('TableOccurrence') }
?uuid :owns ?elemUUID .
?elemUUID :category ?category .
}
GROUP BY ?uuid #and here again
}
}
Комментарии:
1. Идеально и полностью понятно. Однако я не в восторге от производительности на 100%. Есть ли лучший способ достичь этой цели, или это «путь»?
2. Я считаю, что другого способа делать то, что вы хотите, нет. Если у вас есть права на запись, вы всегда можете вставить тройки следующим образом:
INSERT {?a :hasTOCount ?ct} WHERE {SELECT ?a (COUNT(*) AS ?ct) WHERE {...} GROUP BY ?a}
тогда вы можете запросить это напрямую. Это, конечно, может устареть, если данные изменятся. Некоторые хранилища triplestore позволяют вам создавать «правила», которые достигают того же, что и выше, но должны помогать поддерживать согласованную систему.3. Отлично. Спасибо, @Valerio.