2017-08-30 1 views
0

Angesichts dieser Daten, wo jede Person optional ein "intelligentes" Prädikat haben kann und jede Abteilung keine oder mehrere Personen haben kann, muss ich Abteilungen finden, die nur die schlaue Menschen. Das Ergebnis sollte nur die Abteilungen 1 und 2 umfassen. Im Idealfall sollte das Ergebnis auch die "intelligenten" Objekte für jede Abteilung enthalten. Vielen Dank!SPARQL: Objekte mit allen Unterobjekten suchen, die einem Kriterium entsprechen

person:A p:type 'p' ; 
      p:smart 'yes' . 
person:B p:type 'p' ; 
      p:smart 'maybe' . 
person:C p:type 'p' . 

department:1 p:type 'd' ; 
       p:has person:A, person:B . 
department:2 p:type 'd' ; 
       p:has person:B . 
department:3 p:type 'd' ; 
       p:has person:B, person:C . 
department:4 p:type 'd' . 

Antwort

3

Ich habe ein Gefühl, das ich vor etwas ähnliches beantwortet haben, aber trotzdem ist es eine recht nette Art und Weise, dies zu tun:

select ?dept 
    (count(?person) as ?pc) (count(?smart) as ?sc) 
    (group_concat(?smart; separator=',') as ?smarts) 
{ 
    ?dept p:has ?person . 
    optional { ?person p:smart ?smart } 
} 
group by ?dept 
having (?pc = ?sc) 

Das heißt: die Abteilungen, die Menschen finden, und (wo verfügbar) intelligenter Wert. Suchen Sie für jede Abteilung nach der Anzahl der Personen, die der Anzahl der intelligenten Werte entspricht.

------------------------------------------------------------- 
| dept        | pc | sc | smarts  | 
============================================================= 
| <http://example.com/department#2> | 1 | 1 | "maybe"  | 
| <http://example.com/department#1> | 2 | 2 | "yes,maybe" | 
------------------------------------------------------------- 

Wenn Sie wollen Ergebnisse für jedes Objekt zu bekommen, einige Kriterien übereinstimmen, group by/having ist oft die saubersten Antwort (in, dass Sie von Filtern passend trennen kann).

+0

Ich mag diese Lösung wirklich! Ich frage mich, welcher ist in der Regel schneller, aber vielleicht gibt es nicht so viel Unterschied. Wenn ich Zeit habe, probiere ich es in einem kleinen "Benchmark" aus. Prost – AKSW

+0

Ich sollte darauf hinweisen, dass diese Lösung darauf angewiesen ist, höchstens einen intelligenten Wert pro Person zu bringen. Es ist nicht schwer, komplexere Fälle zu lösen, aber sie sind weniger hübsch (die aggregierten Klauseln werden länger). Was die Geschwindigkeit anbetrifft, so vermute ich, dass es für die meisten vernünftigen Geschäfte keinen großen Unterschied gibt (d. H. Sie machen die Filterverbindungen in einer vernünftigen Reihenfolge), aber es wäre interessant zu testen. – user205512

+0

Nun, zumindest ist Ihre Antwort die akzeptierte, also gibt es vielleicht einige Vorteile. Wäre interessant zu wissen, welche: D – AKSW

2

So etwas wie Doppel-Negation funktionieren könnte:

SELECT DISTINCT ?dept WHERE { 
    ?dept p:has ?person . 
    FILTER NOT EXISTS { 
    ?dept p:has ?person1 . 
    FILTER NOT EXISTS { 
    ?person1 p:smart ?smartVal 
    } 
    } 
} 

Ergebnis:

+---------------+ 
|  dept  | 
+---------------+ 
| department:1 | 
| department:2 | 
+---------------+ 

Werte mit:

SELECT ?dept (GROUP_CONCAT(DISTINCT ?smart;separator=";") as ?smartValues) WHERE { 
    ?dept p:has ?person . 
    ?person p:smart ?smart 
    FILTER NOT EXISTS { 
    ?dept p:has ?person1 . 
    FILTER NOT EXISTS { 
    ?person1 p:smart ?smartVal 
    } 
    } 
} 
GROUP BY ?dept 

Ergebnis:

+---------------+-------------+ 
|  dept  | smartValues | 
+---------------+-------------+ 
| department:1 | maybe;yes | 
| department:2 | maybe  | 
+---------------+-------------+ 
Verwandte Themen