Как найти следующее наибольшее значение ресурса с помощью запроса SPARQL - PullRequest
2 голосов
/ 03 апреля 2019

У меня проблемы с решением следующей проблемы: «Постройте график с апоапсисом каждой планеты вместе со ссылкой на планету, которая будет следующей в отношении ее расстояния от Солнца».

Вот дамп графика:

:Saturn  
  skos:exactMatch dbr:Saturn;
  rdf:type dbo:Planet;
  v:orbits :Sun;
  v:apoapsis [rdf:value 9.0412; v:uom unit:AU] ;
  v:orbitalPeriod [rdf:value 29.45; v:uom unit:YR ];
  v:radius [rdf:value 60268; v:uom unit:KM] ;
  v:temperature 
    [rdf:value -139; 
      v:uom unit:Deg_C ];  
.

Итак, на графике приведены некоторые данные о солнечной системе. Все планеты (dbo: Planet) имеют свойство v: apoapsis и значение, указывающее расстояние до Солнца. Я уже выяснил, как найти все большие значения, но я просто хочу следующий самый большой. Результат выглядит так:

:Mars   v:apoapsis    1.666 ;
        v:nextPlanet  :Saturn , :Jupiter , :Uranus .

:Mercury  v:apoapsis  0.467 ;
        v:nextPlanet  :Saturn , :Jupiter , :Uranus , :Mars , :Earth , :Venus .

:Earth  v:apoapsis    1.017 ;
        v:nextPlanet  :Saturn , :Jupiter , :Uranus , :Mars .

:Venus  v:apoapsis    0.728 ;
        v:nextPlanet  :Saturn , :Jupiter , :Uranus , :Mars , :Earth .

:Jupiter  v:apoapsis  5.4588 ;
        v:nextPlanet  :Saturn , :Uranus .

:Saturn  v:apoapsis   9.0412 ;
        v:nextPlanet  :Uranus .

Ожидаемый результат должен выглядеть следующим образом:

:Mars v:apoapsis 1.666 ;
 v:nextPlanet :Jupiter .
:Mercury v:apoapsis 0.467 ;
 v:nextPlanet :Venus .
:Uranus v:apoapsis 20.11 ;
 v:nextPlanet :Neptune .

Я новичок в SPARQL, и мне не нравится идея перебирать элементы для такого рода задач. Полное решение не требуется, я просто хочу знать, как решить эту проблему, и я рад некоторым идеям. Спасибо.

Мой самый заметный запрос выглядит так:

CONSTRUCT{?planet v:apoapsis ?AUdist;
    v:nextPlanet ?nextPlanet .}
WHERE {
  ?planet a dbo:Planet.
  ?planet v:apoapsis ?dist.
          ?dist v:uom unit:AU;
                rdf:value ?AUdist .

  FILTER(?AUdist > ?AUdist2)
  {
    SELECT ?nextPlanet ?AUdist2
        WHERE { 
        ?nextPlanet a dbo:Planet.
        ?nextPlanet v:apoapsis ?dist2.
          ?dist2 v:uom unit:AU;
            rdf:value ?AUdist2 .
        }   
  ORDER BY ASC(?AUdist2) 
  }
   {
  }
}ORDER BY ASC(?AUdist)

Ответы [ 2 ]

2 голосов
/ 03 апреля 2019

Идея состоит в том, чтобы получить минимальное значение расстояния в подзапросе, а затем получить соответствующую планету во внешнем запросе:

CONSTRUCT {
    ?planet v:apoapsis ?dist;
    v:nextPlanet ?nextPlanet .
} WHERE {

    ?planet v:apoapsis ?dist ;
            v:nextPlanet ?nextPlanet .
    ?nextPlanet v:apoapsis ?nextDist
    BIND(abs(?dist - ?nextDist) as ?diff)
    FILTER(?diff = ?minDiff)

  # get planet and the minimum distance to its next planet 
  {
   SELECT ?planet (min(?diff) as ?minDiff) {
    ?planet v:apoapsis ?dist ;
            v:nextPlanet/v:apoapsis ?nextDist
    BIND(abs(?dist - ?nextDist) as ?diff)
  } GROUP BY ?planet
  }
}

Обратите внимание, что запрос здесь начинается с ваших промежуточных результатов.Вы не поделились полными данными, поэтому мне пришлось проверить, что я получил от вас.

0 голосов
/ 03 апреля 2019

Общий подход к такого рода запросам заключается в следующем:

  1. Получить все комбинации значений1 и значений2
  2. Сохранять только те комбинации, в которых значение1 меньше значения2
  3. Используйте GROUP BY и MIN, чтобы найти наименьшее значение2 для данного значения1

Вы уже выполнили шаги 1 и 2. Чтобы немного переписать запрос:

SELECT * {
    ?planet v:apoapsis/rdf:value ?dist.
    ?otherPlanet v:apoapsis/rdf:value ?otherDist.
    FILTER (?dist < ?otherDist)
}

Теперь на шаге 3 мы хотим сгруппировать по ?planet и найти наименьшее ?otherDist в каждой группе:

SELECT ?planet (MIN(?otherDist) AS ?nextDist) {
    ?planet v:apoapsis/rdf:value ?dist.
    ?otherPlanet v:apoapsis/rdf:value ?otherDist.
    FILTER (?dist < ?otherDist)
}
GROUP BY ?planet

Это была сложная часть.Остается только превратить указанный выше запрос в подзапрос внутри запроса CONSTRUCT, который находит ?nextPlanet, соответствующий ?nextDist, и создает целевой граф.

...