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 中明確定義。
有關完整描述,請參見修飾符 章節。
另一種刪除重複項的方法是隻顯示一個可能的值,方法是使用聚合函式 MIN、MAX、SUM 或 AVG 之一。
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 子句(如果存在多個屬性)。