Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Consulta SPARQL para obter todos os pais de um nó


Seus dados podem ser representados em 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 daqui, você só quer uma consulta SPARQL que encontre todas as coisas conectadas a uma classe específica por um caminho (incluindo o caminho vazio) de rdfs:subClassOf propriedades.
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      |
--------------

Os resultados nessa consulta não são necessariamente ordenados por sua posição no caminho (embora neste caso sejam). Se você precisar deles em ordem, você pode fazer isso (que é baseado em esta resposta sobre o cálculo da posição de elementos em uma 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)

Isso encontra cada ancestral ?class de :Win7 bem como cada ?mid ancestral intermediário. Para ancestral ?class , a distância é calculada como o número de relações intermediárias entre (count(?mid) ). Ele ordena os resultados com base nessa distância, então :Win7 é o ancestral mais próximo, :Windows depois disso, e assim por diante.

Você pode até fazer uma formatação sofisticada que deseja assim:
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" |
-----------------------------------

Ele pode ser possível fazer algum processamento de string mais sofisticado e obter a string de várias linhas. Você pode ver a última parte de esta resposta onde há alguma formatação sofisticada para uma matriz de ideias bem alinhada.