sql >> Base de Datos >  >> RDS >> Mysql

Consulta SPARQL para obtener todos los padres de un nodo

Sus datos se pueden representar en RDF como data.n3 :

@prefix : <http://example.org/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

:Network rdfs:subClassOf :Main .

:ATM rdfs:subClassOf :Network .
:ARPANET rdfs:subClassOf :Network .

:Software rdfs:subClassOf :Main .

:Linux rdfs:subClassOf :Software .
:Windows rdfs:subClassOf :Software .

:XP rdfs:subClassOf :Windows .
:Win7 rdfs:subClassOf :Windows .
:Win8 rdfs:subClassOf :Windows .

A partir de aquí, solo desea una consulta SPARQL que encuentre todas las cosas conectadas a una clase en particular por una ruta (incluida la ruta vacía) de rdfs:subClassOf propiedades.

prefix : <http://example.org/>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>

select ?superclass where { 
  :Win7 rdfs:subClassOf* ?superclass
}
--------------
| superclass |
==============
| :Win7      |
| :Windows   |
| :Software  |
| :Main      |
--------------

Los resultados de esa consulta no están necesariamente ordenados por su posición en la ruta (aunque en este caso sí lo están). Si los necesita en orden, puede hacer esto (que se basa en esta respuesta sobre cómo calcular la posición de elementos en una lista RDF ):

prefix : <http://example.org/>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>

select ?class where { 
  :Win7 rdfs:subClassOf* ?mid .
  ?mid rdfs:subClassOf* ?class .
}
group by ?class
order by count(?mid)

Esto encuentra cada ancestro ?class de :Win7 así como cada ?mid antepasado intermedio. Para antepasado ?class , la distancia se calcula como el número de relaciones intermedias entre (count(?mid) ). Ordena los resultados en función de esa distancia, por lo que :Win7 es el antepasado más cercano, :Windows después de eso, y así sucesivamente.

Incluso puede hacer algunos de los formatos sofisticados que desee de esta manera:

prefix : <http://example.org/>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>

select (group_concat( ?name ; separator="--" )  as ?path) where {
  {
    select ?name where { 
      :Win7 rdfs:subClassOf* ?mid .
      ?mid rdfs:subClassOf* ?class .
      bind( strAfter( str(?class), "http://example.org/") as ?name )
    }
    group by ?class ?name
    order by count(?mid)
  }
}
-----------------------------------
| path                            |
===================================
| "Win7--Windows--Software--Main" |
-----------------------------------

podría ser posible hacer un procesamiento de cadenas más elegante y obtener la cadena multilínea. Puede consultar la última parte de esta respuesta donde hay un formato elegante para una matriz bien alineada para las ideas.