跳轉到內容

XQuery/SPARQL 教程

來自華夏公益教科書

SPARQL 介面

[編輯 | 編輯原始碼]

可以使用 SPARQL 透過 XQuery 前端 查詢 emp-dept RDF,該前端連線到 儲存,該儲存由 Talis 提供。此指令碼支援 SPARQL 查詢和瀏覽 RDF 圖。


該介面擴充套件了查詢,例如

  select ?name ?job where {
   ?emp rdf:type  f:emp.
   ?emp foaf:surname ?name.
   ?emp f:Job ?job.
  }

你可以在 這裡 [失效連結] 執行

 prefix foaf: <http://xmlns.com/foaf/0.1/>
 prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
 prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
 prefix f: <http://www.cems.uwe.ac.uk/empdept/concept/>
 prefix xs: <http://www.w3.org/2001/XMLSchema#>
 select ?name ?job 
  where {
   ?emp rdf:type  f:emp.
   ?emp foaf:surname ?name.
   ?emp f:Job ?job.
 }

並將此傳送到 Talis 服務,以一種可以執行的形式,你可以在 這裡 執行。由此產生的 SPARQLQuery Results XML 將被轉換為 HTML。

示例查詢

[編輯 | 編輯原始碼]

列出所有員工

[編輯 | 編輯原始碼]
 select ?emp where {
  ?emp  rdf:type  f:emp.
 }

執行 [失效連結]

按字母順序列出所有員工姓名

[編輯 | 編輯原始碼]
 select ?name where {
  ?emp  rdf:type  f:emp.
  ?emp  foaf:surname ?name. 
 }
 ORDER BY ?name

執行 [失效連結]

列出員工的姓名、薪水、部門編號和職位

[編輯 | 編輯原始碼]
 select ?name ?sal ?dno ?job where {
  ?emp  rdf:type  f:emp;
        foaf:surname ?name;
        f:Sal ?sal;
        f:Dept ?dept;
        f:Job ?job.  
  ?dept f:DeptNo ?dno. 
 }

注意,; 代替 . 重複主題。

這裡 [失效連結] 嘗試此查詢和以下查詢。

列出前 5 位員工

[編輯 | 編輯原始碼]
select ?ename where {
  ?emp  rdf:type  f:emp;
        foaf:surname ?ename.
} 
ORDER BY ?ename
LIMIT 5

按薪水列出前 5 位員工

[編輯 | 編輯原始碼]
select ?ename ?sal where {
 ?emp  rdf:type  f:emp;
       foaf:surname ?ename;
       f:Sal ?sal.
} 
ORDER BY DESC(?sal)
LIMIT 5

列出部門

[編輯 | 編輯原始碼]
select ?dept where {
  ?dept  rdf:type  f:dept.  
}

列出所有部門和所有員工

[編輯 | 編輯原始碼]
select ?dept ?emp where {
  {?dept  rdf:type  f:dept }
  UNION
  {?emp rdf:type f:emp}
}

列出薪水超過 1000 的員工

[編輯 | 編輯原始碼]

如果 RDF 文字被型別化,例如,作為 xs:integer,就像此生成的 RDF 中一樣,那麼以下查詢將選擇薪水大於 1000 的員工


select ?emp ?sal where {
  ?emp  rdf:type  f:emp;
        f:Sal ?sal.
  FILTER (?sal > 1000)
}

如果 RDF 文字未被型別化,則必須轉換變數

 select ?emp ?sal where {
  ?emp  rdf:type  f:emp;
        f:Sal ?sal.
  FILTER (xs:integer(?sal) > 1000)
}

列出員工及其工作地點

[編輯 | 編輯原始碼]
select ?emp ?loc where {
  ?emp  rdf:type  f:emp.
  ?emp f:Dept ?dept.
  ?dept f:Location ?loc.
}

列出員工姓名及其經理

[編輯 | 編輯原始碼]
select ?ename ?mname where {
  ?emp  rdf:type  f:emp;
        f:Mgr ?mgr;
        foaf:surname ?ename.
  ?mgr foaf:surname ?mname.
} 

包含沒有經理的員工

[編輯 | 編輯原始碼]
select ?ename ?mname where {
  ?emp  rdf:type  f:emp;
        foaf:surname ?ename.
  OPTIONAL {?emp f:Mgr ?mgr.
            ?mgr foaf:surname ?mname.
           }
}

列出沒有經理的員工

[編輯 | 編輯原始碼]
select ?ename where {
  ?emp  rdf:type  f:emp;
        foaf:surname ?ename.
  OPTIONAL {?emp f:Mgr ?mgr}
  FILTER (!bound(?mgr))
}

列出員工的不同位置

[編輯 | 編輯原始碼]
select distinct ?loc  where {
  ?emp  rdf:type  f:emp.
  ?emp  f:Dept ?dept.
  ?dept f:Location ?loc.
} 


列出擔任分析師的員工的詳細資訊

[編輯 | 編輯原始碼]
select * where {
  ?emp  rdf:type  f:emp.
  ?emp  f:Dept ?dept.
  ?dept f:Location ?loc.
  ?emp f:Job ?job.
  FILTER (?job = "ANALYST")
} 


列出擔任分析師或經理的員工

[編輯 | 編輯原始碼]
select ?emp where {
  ?emp  rdf:type  f:emp;
        f:Job ?job.
  FILTER (?job = "ANALYST"  || ?job = "MANAGER")
}

列出既不是分析師也不是經理的員工

[編輯 | 編輯原始碼]
select * where {
   ?emp  rdf:type  f:emp;
         f:Job ?job.
   FILTER (?job != "ANALYST"  && ?job != "MANAGER")
}

列出姓氏以“S”開頭的員工

[編輯 | 編輯原始碼]
select * where {
  ?emp  rdf:type  f:emp.
  ?emp foaf:surname ?ename.
  FILTER (regex(?ename, "^S"))
} 

列出姓氏包含“AR”的員工

[編輯 | 編輯原始碼]
select * where {
  ?emp  rdf:type  f:emp.
  ?emp foaf:surname ?ename.
  FILTER (regex(?ename, "AR"))
} 

列出姓氏包含“M”後跟“R”的員工,不區分大小寫

[編輯 | 編輯原始碼]
select * where {
  ?emp  rdf:type  f:emp.
  ?emp foaf:surname ?ename.
  FILTER (regex(?ename, "m.*r","i"))
}

計算最高薪水

[編輯 | 編輯原始碼]

SPARQL 1.0 缺少 min() 或 max(),雖然它們已新增到一些實現中。以下方法,由 Dean Allemang 提供,可以用來計算最高薪水

select ?maxemp ?maxsal where {
 ?maxemp  rdf:type  f:emp.
 ?maxemp  f:Sal ?maxsal.
 OPTIONAL { ?emp rdf:type f:emp.
            ?emp f:Sal ?sal.
            FILTER ( ?sal > ?maxsal)
          }.
 FILTER (!bound (?sal))
}


它是如何工作的?我們想要找到最高員工的最高薪水。對於這樣的員工,OPTIONAL 子句將不匹配,因為沒有薪水更高的員工,因此 ?sal 將不會繫結。

在 SPARQL 1.1 中,允許使用 max() 和 min(),因此返回最高薪水的查詢變為

select (max(?sal) as ?maxsal) where {
  ?maxemp  rdf:type  f:emp.
  ?maxemp  f:Sal ?sal.
}

計算薪水相同的員工

[編輯 | 編輯原始碼]
 select * where {
    ?emp1 f:Sal ?sal.
    ?emp2 f:Sal ?sal.
    FILTER (?emp1 != ?emp2)
 }

獲取 SMITH 所屬的部門

[編輯 | 編輯原始碼]
select ?dname  where {
  ?emp  rdf:type  f:emp.
  ?emp f:Dept ?dept.
  ?emp foaf:surname "SMITH".
  ?dept f:Dname ?dname.
}

列出會計部門員工的姓名

[編輯 | 編輯原始碼]
select ?ename  where {
  ?emp  rdf:type  f:emp.
  ?emp f:Dept ?dept.
  ?emp foaf:surname ?ename.
  ?dept f:Dname "Accounting".
} 


本世紀錄用的員工

[編輯 | 編輯原始碼]
select ?ename ?hire where {
 ?emp  rdf:type  f:emp.
 ?emp f:HireDate ?hire.
 ?emp foaf:surname ?ename.
 FILTER (?hire > "2000-01-01"^^xs:date) 
}

請注意,字面量需要型別化才能使比較有效。

列出經理在不同部門的員工的姓名

[編輯 | 編輯原始碼]
select ?name ?edname ?mdname {
  ?emp  rdf:type  f:emp;
        foaf:surname ?name;
        f:Dept ?dept;
        f:Mgr ?mgr.
  
   ?mgr f:Dept ?mdept. 
   ?dept f:Dname ?edname.
   ?mdept f:Dname ?mdname.
   FILTER (?dept != ?mdept)
}

列出員工的等級

[編輯 | 編輯原始碼]

從關係的角度來看,這是員工表和 salgrade 表之間的 theta 連線。

select ?ename ?grade where {
 ?emp  rdf:type  f:emp;
       foaf:surname ?ename;
       f:Sal ?sal.
 ?salgrade rdf:type f:salgrade; 
       f:LoSal ?low; 
       f:HiSal ?high;
       f:Grade ?grade.
   
 FILTER (?sal >= ?low && ?sal <= ?high)
 }

簡化的查詢語法

[編輯 | 編輯原始碼]

一個新的字首簡化了透過其 URI 引用單個資源。

 prefix e: <http://www.cems.uwe.ac.uk/empdept/emp/>
 select ?sal  where {
    e:7900 f:Sal ?sal.
 }

 select ?sal  where {
    <http://www.cems.uwe.ac.uk/empdept/emp/7900> f:Sal ?sal.
 }

的簡寫。

prefix : <http://www.cems.uwe.ac.uk/empdept/concept/>
select ?name ?sal ?dno ?job where {
 ?emp  rdf:type  :emp;
       foaf:surname ?name;
       :Sal ?sal;
       :Dept ?dept;
       :Job ?job.  
 ?dept :DeptNo ?dno. 
}

我們還可以引入一個預設名稱空間

prefix : <http://www.cems.uwe.ac.uk/empdept/concept/>
select ?name ?sal ?dno ?job where {
 ?emp  a :emp;
       foaf:surname ?name;
       :Sal ?sal;
       :Dept ?dept;
       :Job ?job.  
 ?dept :DeptNo ?dno. 
}

並使用縮寫a表示 rdf:type

prefix : <http://www.cems.uwe.ac.uk/empdept/concept/>
select ?name ?sal ?dno ?job where {
 [ a :emp;
   foaf:surname ?name;
   :Sal ?sal;
   :Dept ?dept;
   :Job ?job
 ].
 ?dept :DeptNo ?dno. 
}

如果我們不需要返回資源本身,它可以是匿名的

聚合功能

[編輯 | 編輯原始碼]


雖然 count() 和 sum() 等聚合函式和 GROUP BY 子句在 SPARQL 1.0 中沒有定義,但它們在一些服務(例如 Talis 平臺)上是可用的,在 SPARQL 1.1 標準化之前。

統計部門數量
select (count(?dept) as ?count) where {
  ?dept  rdf:type  f:dept.

}

[編輯 | 編輯原始碼]

統計每個部門的員工數量
select distinct ?dept (count(?emp) as ?count) where {
  ?dept a f:dept.
  ?emp f:Dept ?dept.
} group by ?dept

[編輯 | 編輯原始碼]

通用查詢

[編輯 | 編輯原始碼]

三元組資料模型的統一性使我們能夠以非常通用的方式查詢資料集,如果我們對資料一無所知,這將非常有用。

列出所有資料
select * where {
 ?s ?p ?o
}

[編輯 | 編輯原始碼]

select * where {
 ?s ?p ?o
} LIMIT 20 

這在現實資料集上是不可行的,但可以透過限制返回的三元組數量來獲取三元組樣本。

列出所有員工資料
select ?prop ?val where {
  ?emp  rdf:type  f:emp.
  ?emp ?prop ?val.
}
select distinct ?type where {
  ?s a ?type
}

這表明定義 emp 詞彙表的三個元組在同一個資料集中。

有哪些屬性?

[編輯 | 編輯原始碼]
select distinct ?prop where {
   ?s ?prop ?o
}

屬性的域是什麼?

[編輯 | 編輯原始碼]
select distinct ?type where {
    ?s f:Sal ?v.
    ?s a ?type.
}

屬性的範圍是什麼?

[編輯 | 編輯原始碼]
select distinct ?type where {
    ?s f:Sal ?o.
    ?o a ?type.
}


此查詢僅查詢作為資料集中型別例項的範圍。Sal 的範圍是 xs:integer,但很難用 SPARQL 查詢發現這一點。


select distinct ?type where {
    ?s f:Mgr ?o.
    ?o a ?type.
}

哪些屬性的域是給定的型別?

[編輯 | 編輯原始碼]
select distinct ?prop where {
     ?s a f:salgrade.
     ?s ?prop [].
}

模式查詢

[編輯 | 編輯原始碼]

模式資料的出現使 SPARQL 可以用來查詢此元資料。可以將結果與透過直接查詢資料獲得的結果進行比較。

哪些屬性的域是給定的型別?

[編輯 | 編輯原始碼]
select ?prop  where {
   ?prop rdfs:domain f:emp.
}


請注意,這隻會返回 empdept 詞彙表中的屬性,而不是原始資料中使用的 foaf name 屬性。

員工有哪些整數屬性?

[編輯 | 編輯原始碼]
select ?prop  where {
   ?prop rdfs:domain f:emp.
   ?prop rdfs:range xs:integer.
}

哪些型別的資源有工資?

[編輯 | 編輯原始碼]
select ?type where {
  f:Sal rdfs:domain ?type.
}


可以對資料和詞彙表進行查詢


經理有哪些文字屬性?

[編輯 | 編輯原始碼]
select DISTINCT ?prop  where {
   ?x f:Job "MANAGER".
   ?x a ?type. 
   ?prop rdfs:domain ?type.
   ?prop rdfs:range rdfs:literal.
}

待辦事項

[編輯 | 編輯原始碼]
  • 示例 RDF 缺少語言標籤,這些標籤是演示 lang() 函式所必需的
  • 所有查詢將與 SQL 和 XQuery 等效項一起移至程式碼列表
華夏公益教科書