2012-07-10 25 views
7

Tengo una consulta sparql que devuelve duplicados, y quiero que los limpie solo en uno de los valores (subjectID). A diferencia de DISTINCT que parece encontrar un valor único para la combinación de valores seleccionados, en lugar de solo para uno de los parámetros. Vi a alguien aquí proponer un grupo, pero eso solo parece aplicable si enumero todos los parámetros después de agrupar (mi punto final sparql se queja, por ejemplo, variable de clave no grupal en SELECCIONAR:? Ocupación). He intentado ejecutar una selección interna, pero no parece funcionar para esta consulta específica. Entonces, ¿podría ser un problema con la consulta en sí misma (los valores de la opción de aliveIn parecen estar causando el duplicado)?Teclas Sparql contra valores distintos

Si bien estamos lo suficientemente contentos con los DB relacionales al principio de la curva de aprendizaje con SPARQL, ¡así que no dude en explicar lo obvio para los que no están iniciados! :)

select distinct 
    ?subjectID ?englishName ?sex ?locatedIn15Name 
    ?dob ?dod ?dom ?bornLocationName ?occupation 
    where { 
     ?person a hc:Person ; 
     hc:englishName ?englishName ; 
     hc:sex ?sex; 
     hc:subjectID ?subjectID; 
     optional { ?person hc:livedIn11 ?livedIn11 . 
      ?livedIn11 hc:englishName ?lived11LocationName . 
      ?livedIn11 hc:locatedIn11 ?locatedIn11 . 
      ?locatedIn11 hc:englishName ?locatedIn11Name . 
      ?locatedIn11 hc:locatedIn15 ?locatedIn15 . 
?locatedIn15 hc:englishName ?locatedIn15Name . 
} . 
     optional {?person hc:born ?dob } . 
     optional {?person hc:dateOfDeath ?dod } . 
     optional {?person hc:dateOfMarriage ?dom } . 
     optional { ?person hc:bornIn ?bornIn . 
     ?bornIn hc:englishName ?bornLocationName . 
      ?bornIn hc:easting ?easting . 
      ?bornIn hc:northing ?northing } . 
     optional { ?person hc:occupation ?occupation } 
     FILTER regex(?englishName, "^FirstName LastName") 
     } 
    GROUP BY 
    ?subjectID ?englishName ?sex 
    ?locatedIn15Name ?dob ?dod ?dom 
    ?bornLocationName ?occupation 

Respuesta

12

Re el mensaje de error: variable clave

no en grupo SELECT:? Ocupación

Esto se puede evitar mediante el uso del agregado SAMPLE() - Esto le permitirá simplemente agrupe en ?subjectID pero aún así seleccione valores para el resto de las variables siempre que solo le interese obtener un valor para esas otras variables.

Aquí es un simple ejemplo de esto:

SELECT ?subjectID (SAMPLE(?dob) AS ?dateOfBirth) 
WHERE 
{ 
    ?person a hc:Person ; 
      hc:subjectID ?subjectID . 
    OPTIONAL { ?person hc:born ?dob } 
} 
GROUP BY ?subjectID 
+0

+1 para el uso (muy poco ortodoxo) de SAMPLE. –

+0

Gracias Rob, ¡eso es muy útil! Supongo que es un muestreo un tanto no determinista, para ser usado con precaución. :) – Nava

+0

PD Votará una vez que gane un poco más de reputación. – Nava

9

La primera cosa a tener en cuenta es que no hay tal cosa como una clave, en realidad, en RDF/SPARQL. Está consultando un gráfico, y ?subjectID puede tener simplemente varias combinaciones posibles de valores para las otras variables que está seleccionando. Esto se debe a la forma del gráfico que está consultando: quizás su persona tenga más de un nombre en inglés, o al revés: el mismo nombre en inglés puede ser compartido por más de una persona.

Una consulta SPARQL SELECT es una extraña bestia: consulta una estructura de gráfico pero presenta el resultado como una tabla plana (técnicamente, es una secuencia de conjuntos de enlaces variables, pero equivale a lo mismo). Los duplicados se producen porque se pueden encontrar diferentes combinaciones de valores para sus variables básicamente siguiendo diferentes caminos en el gráfico.

El hecho de que obtenga valores duplicados para ?subjectID en su resultado es por lo tanto inevitable, simplemente porque estos, desde el punto de vista del gráfico RDF, son soluciones únicas para su consulta. No puede filtrar los resultados sin perder realmente la información, por lo que en general es difícil darle una solución sin saber más acerca de que 'duplica' desea descartar: ¿quiere un único nombre en inglés para cada tema, o una posible fecha de nacimiento (a pesar de que puede haber más de uno en sus datos)?

Sin embargo, aquí hay algunos consejos para el manejo/procesing tales resultados con mayor facilidad:

En primer lugar, podría elegir utilizar una cláusula ORDER BY en su variable de ?subjectID. Esto todavía le dará varias filas con el mismo valor para ?subjectID, pero todas estarán en orden, por lo que puede procesar su resultado de manera más eficiente.

Otra solución es dividir su consulta en dos: haga una primera consulta que solo selecciona todos los temas únicos (y posiblemente todos los demás valores que usted sabe, de antemano, que serán únicos dado el tema), luego itere sobre el resultado y haga una consulta por separado para obtener los otros valores que le interesan, para cada valor de subjectID individual. Esta solución puede sonar como una herejía (especialmente si proviene de un fondo de SQL), pero en realidad podría ser más rápido y más fácil que intentar hacer todo en una gran consulta.

Otra solución más es la sugerida por RobV: el uso de un agregado SAMPLE en una variable particular para simplemente seleccionar un valor único (aleatorio). Una variación de esto es usar el agregado GROUP_CONCAT, que crea un único valor al concatenar todos los valores posibles en una sola cadena.

+0

Wow, gracias, eso es inmensamente útil. He aprendido mucho leyendo tu respuesta. Mientras esperaba, refactoré un poco y dividiría la consulta en dos. Va en contra de mi sentido de la eficiencia, pero es una solución limpia y simple. Nunca he usado 'GROUP_CONCAT' en SQL, pero básicamente esto resuelve mi pregunta de qué hacer con la estructura de gráficos planos. Mi siguiente pregunta, ¡prevenida ya! (como con RobV, vota a seguir cuando me he ganado un poco más de reputación) – Nava

Cuestiones relacionadas