跳轉到內容

SPARQL/SELECT

來自華夏公益教科書,開放的書籍,開放的世界

SELECT 語句包含 2 或 3 個部分。

SELECT  ... query result variables ...
WHERE {
        ... query pattern ...
}
        ... optional query modifiers ...
GROUP BY ...
HAVING ...
ORDER BY ...
LIMIT ...

第一部分是查詢結果變數。這些將在查詢執行時顯示。第二部分是包含查詢模式的 WHERE 子句。這定義了資料選擇並生成變數,最後一部分是可選修飾符。

示例

SELECT ?child ?childLabel
WHERE
{
# ?child  father   Bach
  ?child wdt:P22 wd:Q1339.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}

試試看!

查詢結果變數

[編輯 | 編輯原始碼]

SELECT ?child ?childLabel ... 在上面的示例中,?child?childLabel 是變數。變數用空格隔開。可以使用 AS 為變數顯示另一個名稱(別名),例如 (?child AS ?Child_of_Bach)。注意,別名也應該是一個變數,並且組合應該以括號 (?a AS ?b) 開頭和結尾。
PS。對於標籤的別名,標籤應該在 SERVICE 中明確定義。或者,變數也可以根據那裡的要求命名。

SELECT (?child AS ?Child_of_Bach) (?childLabel AS ?Name)
WHERE
{
# ?child  father   Bach
  ?child wdt:P22 wd:Q1339.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". 
                           ?child rdfs:label ?childLabel.
                         }
}

試試看!

查詢模式

[編輯 | 編輯原始碼]

查詢模式指定資料選擇並生成變數。

# ?child  father   Bach
  ?child wdt:P22 wd:Q1339.

在本例中,三元組 ?child wdt:p22 wd:Q1339 指定變數 ?child 必須具有父/父親巴赫。

三元組的任何部分(主體、謂詞和賓語)都可以是變數。這使得這種選擇非常靈活。

可以新增更多三元組,例如顯示性別、出生日期和死亡日期。每個句子 應該以句號結尾。新變數應該新增到頂部(查詢結果變數)以顯示它們。

SELECT ?child ?childLabel ?genderLabel ?birth_date ?date_of_death
WHERE
{
  ?child wdt:P22 wd:Q1339.# ?child  has father   Bach
  ?child wdt:P21 ?gender.
  ?child wdt:P569 ?birth_date.
  ?child wdt:P570 ?date_of_death.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}

試試看!

可選查詢修飾符

[編輯 | 編輯原始碼]

有關完整描述,請參見修飾符 章節。

透過在 WHERE { } 子句的最後一個大括號後新增 ORDER BY ?birth_date,可以按出生日期對上述查詢進行排序。

SELECT ?child ?childLabel ?genderLabel ?birth_date ?date_of_death
WHERE
{
  ?child wdt:P22 wd:Q1339.# ?child  has father   Bach
  ?child wdt:P21 ?gender.
  ?child wdt:P569 ?birth_date.
  ?child wdt:P570 ?date_of_death.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
ORDER BY ?birth_date

試試看!

刪除重複項

[編輯 | 編輯原始碼]

您可能已經注意到,上述查詢產生了 21 條記錄,而巴赫只有 20 個孩子。這是由於約翰·克里斯托夫·弗里德里希·巴赫 有 2 個條目,因為有 2 個不同的出生日期,分別為 1732 年 6 月 21 日和 23 日。

通常建議在結果變數中使用 DISTINCT,例如

SELECT DISTINCT ?child ?childLabel ?genderLabel ?birth_date ?date_of_death
WHERE
{
  ?child wdt:P22 wd:Q1339.# ?child  has father   Bach
  ?child wdt:P21 ?gender.
  ?child wdt:P569 ?birth_date.
  ?child wdt:P570 ?date_of_death.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
ORDER BY ?child

試試看!

DISTINCT 刪除重複條目,但在本例中沒有幫助,因為條目是不同的。為了有所幫助,所有引數都應該相等。

有幫助的是按孩子分組,併合並 ?birth_date 的值。同樣,?date_of_death?genderLabel 也被分組以保持一致。

SELECT ?child ?childLabel 
       (GROUP_CONCAT(DISTINCT ?genderLabel;   SEPARATOR=", ") AS ?genderLabels)
       (GROUP_CONCAT(DISTINCT ?birth_date;    SEPARATOR=", ") AS ?birth_dates)
       (GROUP_CONCAT(DISTINCT ?date_of_death; SEPARATOR=", ") AS ?dates_of_death)
WHERE
{
  ?child wdt:P22 wd:Q1339.# ?child  has father   Bach
  ?child wdt:P21 ?gender.
  ?child wdt:P569 ?birth_date.
  ?child wdt:P570 ?date_of_death.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". 
                           ?child  rdfs:label ?childLabel.
                           ?gender rdfs:label ?genderLabel.
                         }
}
GROUP BY ?child ?childLabel
ORDER BY ?birth_dates

試試看!

使用的可選查詢修飾符是 GROUP BY,變數透過使用 (GROUP_CONCAT(DISTINCT ?var1; SEPARATOR=", ") AS ?var2) 來合併。ORDER BY 已透過使用合併後的變數 ?birth_dates 而不是 ?birth_date 進行修改。所有標籤都應該在 SERVICE 中明確定義。

有關完整描述,請參見修飾符 章節。

另一種刪除重複項的方法是隻顯示一個可能的值,方法是使用聚合函式 MINMAXSUMAVG 之一。

SELECT ?child ?childLabel 
       (MIN(?genderLabel)   AS ?genderlabel1) 
       (MIN(?birth_date)    AS ?birth_date1) 
       (MAX(?date_of_death) AS ?date_of_death1)
WHERE
{
  ?child wdt:P22 wd:Q1339.# ?child  has father   Bach
  ?child wdt:P21 ?gender.
  ?child wdt:P569 ?birth_date.
  ?child wdt:P570 ?date_of_death.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". 
                           ?child  rdfs:label ?childLabel.
                           ?gender rdfs:label ?genderLabel.
                         }
}
GROUP BY ?child ?childLabel
ORDER BY ?birth_date1

試試看!

使用的可選查詢修飾符也是 GROUP BY,變數透過使用 (MIN(?var) AS ?var1) 來合併。ORDER BY 已透過使用第一個出生日期 ?birth_date1 而不是 ?birth_date 進行修改。所有標籤也應該在 SERVICE 中明確定義。

新增缺失條目

[編輯 | 編輯原始碼]

讓我們嘗試對奧巴馬 (Q76) 的上述查詢之一。

SELECT DISTINCT ?child ?childLabel ?genderLabel ?birth_date ?date_of_death
WHERE
{
  ?child wdt:P22 wd:Q76.# ?child  has father   Obama
  ?child wdt:P21 ?gender.
  ?child wdt:P569 ?birth_date.
  ?child wdt:P570 ?date_of_death.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
ORDER BY ?child

試試看!

這將導致沒有結果,儘管奧巴馬有兩個孩子。原因是,為了匹配這個查詢,一個潛在的結果(孩子)必須匹配我們列出的所有三元組:它必須有性別、出生日期和死亡日期。如果其中一個或多個屬性不存在,它將不會匹配。這不是我們想要的結果:我們主要想要所有孩子的列表——如果其他資料可用,我們希望將其包含在內,但我們不希望它限制我們的結果列表。

解決方案是告訴 WDQS 這些三元組是 OPTIONAL

SELECT DISTINCT ?child ?childLabel ?genderLabel ?birth_date ?date_of_death
WHERE
{
  ?child wdt:P22 wd:Q76.# ?child  has father   Obama
  OPTIONAL{ ?child wdt:P21 ?gender. }
  OPTIONAL{ ?child wdt:P569 ?birth_date. }
  OPTIONAL{ ?child wdt:P570 ?date_of_death. }
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
ORDER BY ?child

試試看!

現在顯示了兩個孩子,很明顯死亡日期還沒有填寫,因為這些孩子還活著。

有關完整描述,請參見可選 章節。

萬無一失:新增缺失條目並刪除重複條目

[編輯 | 編輯原始碼]

任何給定父親的孩子及其詳細資訊的萬無一失列表將是

SELECT ?child ?childLabel 
       (GROUP_CONCAT(DISTINCT ?genderLabel;   SEPARATOR=", ") AS ?genderLabels)
       (GROUP_CONCAT(DISTINCT ?birth_date;    SEPARATOR=", ") AS ?birth_dates)
       (GROUP_CONCAT(DISTINCT ?date_of_death; SEPARATOR=", ") AS ?dates_of_death)
WHERE
{
  ?child wdt:P22 wd:Q76.# ?child  has father   Obama
  OPTIONAL{ ?child wdt:P21 ?gender. }
  OPTIONAL{ ?child wdt:P569 ?birth_date. }
  OPTIONAL{ ?child wdt:P570 ?date_of_death. }
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". 
                           ?child  rdfs:label ?childLabel.
                           ?gender rdfs:label ?genderLabel.
                         }
}
GROUP BY ?child ?childLabel
ORDER BY ?birth_dates

試試看!

這結合了 OPTIONAL 子句(如果屬性不存在)和 GROUP_CONCAT 子句(如果存在多個屬性)。


華夏公益教科書