SPARQL/表达式和函数
BIND( expression AS ?variable ).
语句可用于将表达式的结果分配给变量(通常是新变量,但您也可以覆盖现有变量)。
# Persons died by capital punishment
SELECT ?person ?personLabel ?personDescription ?age
WHERE
{
?person wdt:P31 wd:Q5;
wdt:P569 ?born;
wdt:P570 ?died;
wdt:P1196 wd:Q8454.
BIND(?died - ?born AS ?ageInDays).
BIND(?ageInDays/365.2425 AS ?ageInYears).
BIND(FLOOR(?ageInYears) AS ?age).
# or, as one expression:
#BIND(FLOOR((?died - ?born)/365.2425) AS ?age).
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
BIND
还可以用于将常量值简单地绑定到变量,以提高可读性。例如,查找所有女性牧师的查询
SELECT ?woman ?womanLabel
WHERE
{
?woman ?instanceOf ?human;
?sexOrGender ?female;
?occupation ?priest.
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
# linking to wikidata Q and P codes
BIND(wdt:P31 AS ?instanceOf).
BIND(wd:Q5 AS ?human).
BIND(wdt:P21 AS ?sexOrGender).
BIND(wd:Q6581072 AS ?female).
BIND(wdt:P106 AS ?occupation).
BIND(wd:Q42603 AS ?priest).
}
以上结果与以下结果相同
SELECT ?woman ?womanLabel
WHERE
{
?woman wdt:P31 wd:Q5; # instance of human
wdt:P21 wd:Q6581072; # sex or gender female
wdt:P106 wd:Q42603. # occupation priest
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
IF( condition, thenExpression, elseExpression )
表达式用于根据条件分配不同的值。
例如,为了计算年龄,精确到天。在表达式 BIND( .... - (IF( condition,1,0 ) AS ?age)
中,条件确定从 ?age
中减去 1 或 0(无),具体取决于出生日期和死亡日期的月份和日期。
# Query to find all musicians who have already died
# calculate their age (full years) at death
# count how many of them died at each age
#defaultView:LineChart
SELECT ?age (COUNT (DISTINCT ?a) AS ?count)
WHERE {
?a wdt:P31 wd:Q5. #instance of human
?a wdt:P106/wdt:P279 wd:Q639669. #occupation a subclass of musician
?a p:P569/psv:P569 ?birth_date_node.
?a p:P570/psv:P570 ?death_date_node.
?birth_date_node wikibase:timeValue ?birth_date.
?death_date_node wikibase:timeValue ?death_date.
BIND( YEAR(?death_date) - YEAR(?birth_date) -
IF(MONTH(?death_date)<MONTH(?birth_date) ||
(MONTH(?death_date)=MONTH(?birth_date) && DAY(?death_date)<DAY(?birth_date)),1,0) AS ?age )
# calculate the age, precisely to the day (times and timezones ignored)
FILTER(?age > 10 && ?age < 100). #ignore outlyers, several of which are probably errors
}
GROUP BY ?age
ORDER BY ?age
以下是一个将人口划分为组的示例。#defaultView:Map
中的 ?layer
将其显示为不同的颜色。
#Big cities, grouped into map layers by population
#defaultView:Map
SELECT DISTINCT ?city ?cityLabel (SAMPLE(?location) AS ?location) (MAX(?population) AS ?population) (SAMPLE(?layer) AS ?layer)
WHERE
{
?city wdt:P31/wdt:P279* wd:Q515;
wdt:P625 ?location;
wdt:P1082 ?population.
FILTER(?population >= 500000).
BIND(
IF(?population < 1000000, "<1M",
IF(?population < 2000000, "1M-2M",
IF(?population < 5000000, "2M-5M",
IF(?population < 10000000, "5M-10M",
IF(?population < 20000000, "10M-20M",
">20M")))))
AS ?layer).
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
GROUP BY ?city ?cityLabel
ORDER BY ?population
可以使用熟悉的数学运算符:+
、-
、*
、/
来添加、减去、乘以或除以数字。
运算符 <
、>
、=
、<=
、>=
可用于比较值。比较也为其他类型定义;例如,"abc" < "abd"
为真(词法比较),"2016-01-01"^^xsd:dateTime > "2015-12-31"^^xsd:dateTime
和 wd:Q4653 != wd:Q283111
也是如此。不等式测试 ≠ 写为 !=
。!
也可以用作结果为布尔值的函数的前缀,如 !BOUND
和 !REGEX
。
布尔条件可以使用 &&
(逻辑与:a && b
当 a
和 b
都为真时为真)和 ||
(逻辑或:a || b
当 a
和 b
中的任何一个(或两者)为真时为真)来组合。
例如 IF( ?a != ?b, ... , ... )
和 IF( ?a = ?b && ?c = ?d, ... , ... )
。
VALUES ?var { val1 ... }
语句生成一个具有一个或多个值的变量。这些值可以是任何类型,如数字、字符串,甚至项目,如 VALUES ?number { 1 2 3 }
、VALUES ?abc { "a" "b" "c" }
或 VALUES ?city { wd:Q84 wd:Q90 }.
。
SELECT ?city ?cityLabel WHERE {
VALUES ?city { wd:Q84 wd:Q90 }. # London, Paris
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
值也可以具有更多维度。维度通过 ( ) 分组,如 VALUES ( ?varA ?varB ... ) { ( valA1 valB1 ... ) ... }
。
SELECT ?country ?capital WHERE {
VALUES ( ?country ?capital ) {
( "United Kingdom" "London" )
( "France" "Paris" )
( "Etc" UNDEF ) # Use UNDEF for an undefined value
}
}
SPARQL 中的每个值都有一个类型,它告诉您值的类型以及您可以对其进行的操作。最重要的类型是
- 项目,如
wd:Q42
,代表 道格拉斯·亚当斯 (Q42). - 布尔值,具有两个可能的值
true
和false
。布尔值不会存储在语句中,但许多表达式会返回布尔值,例如2 < 3
(true
) 或"a" = "b"
(false
)。 - 字符串,一段文本。字符串文字用双引号括起来。
- 单语文本,带语言标签的字符串。在文字中,您可以在字符串后面添加一个
@
符号来添加语言标签,例如"Douglas Adams"@en
。 - 数字,可以是整数 (
1
) 或小数 (1.23
)。 - 日期。可以通过在 ISO 8601 日期字符串中添加
^^xsd:dateTime
(区分大小写 -^^xsd:datetime
不起作用!)来写入日期字面值:"2012-10-29"^^xsd:dateTime
。
# Date related properties of Bach
SELECT ?predicate ?pLabel ?object
WHERE
{
wd:Q1339 ?predicate ?object. # Bach
FILTER(DATATYPE(?object) = xsd:dateTime).
BIND( IRI(REPLACE( STR(?predicate),"prop/direct/","entity/" )) AS ?p).
# or ?p wikibase:directClaim ?predicate.
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
ORDER BY ?object
一些数据类型是 rdf:langString、xsd:string、xsd:integer、xsd:dateTime、xsd:decimal 或 "<http://www.opengis.net/ont/geosparql#wktLiteral>"。
STR
[edit | edit source]STR( value )
函数将值转换为字符串。它还会解析 前缀,例如 wd:Q1339 将被转换为 http://www.wikidata.org/entity/Q1339。它的反向操作是 IRI( string )
,它将字符串转换为 IRI。
SELECT ?item ?itemLabel ?string ?stringLabel ?iri ?iriLabel
WHERE {
VALUES ?item { wd:Q1339 }.
BIND( STR(?item) AS ?string ).
BIND( IRI(?string) AS ?iri ).
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
IRI
[edit | edit source]IRI( string )
,它通过应用 前缀 将字符串转换为 IRI。
在下面的示例中,像 wdt:P569
这样的谓词被转换为字符串 http://www.wikidata.org/prop/direct/P569。要获取谓词的标签,首先需要将其替换为实体(http://www.wikidata.org/entity/P569),然后使用 IRI
转换为 wd:P569
。然后可以将它的标签显示为 "出生日期 (P569)"。
# Date related properties of Bach
SELECT ?object ?predicate ?string ?entity ?p ?pLabel
WHERE
{
wd:Q1339 ?predicate ?object. # Bach
FILTER(DATATYPE(?object) = xsd:dateTime).
BIND( STR(?predicate) AS ?string ).
BIND( REPLACE( ?string,"prop/direct/","entity/" ) AS ?entity ).
BIND( IRI(?entity) AS ?p ).
# or all on one line:
# BIND( IRI(REPLACE( STR(?predicate),"prop/direct/","entity/" )) AS ?p).
# This can also be written as: ?p wikibase:directClaim ?predicate.
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
ORDER BY ?object
LANG
[edit | edit source]LANG( string )
函数检索 标签、描述、别名 和 单语文本 的语言标签。
#Countries in European Union with native name and language
SELECT ?country ?countryLabel ?nativename ?language
WHERE
{
wd:Q458 wdt:P150 ?country. # European Union contains administrative territorial entity
OPTIONAL { ?country wdt:P1705 ?nativename.
BIND( LANG(?nativename) AS ?language). }
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
ORDER BY DESC(?language)
BOUND
[edit | edit source]BOUND( variable )
函数如果变量绑定到值则返回 true。否则返回 false。BOUND
表达式经常与 IF(condition,thenExpression,elseExpression)
表达式一起使用。例如,假设您有一个显示一些人的查询,并且您希望显示他们的 笔名 (P742)(如果他们有的话),而不是仅仅显示他们的标签,只有在没有笔名的情况下才使用标签。为此,您在 OPTIONAL
子句中选择笔名(它必须是可选的 - 您不希望丢弃没有笔名的结果),然后使用 BIND(IF(BOUND(…
来选择笔名或标签。
SELECT ?writer ?label
WHERE
{
?writer wdt:P31 wd:Q5; # French writer
wdt:P27 wd:Q142;
wdt:P106 wd:Q36180;
wdt:P569 ?dob.
FILTER("1751-01-01"^^xsd:dateTime <= ?dob && ?dob < "1801-01-01"^^xsd:dateTime) # born in the second half of the 18th century
?writer rdfs:label ?writerLabel. # get the English label
FILTER(LANG(?writerLabel) = "en")
OPTIONAL { ?writer wdt:P742 ?pseudonym. } # get the pseudonym, if it exists
BIND(IF(BOUND(?pseudonym),?pseudonym,?writerLabel) AS ?label). # bind the pseudonym, or if it doesn’t exist the English label, as ?label
}
IN 和 NOT IN
[edit | edit source]value IN( list of values )
函数检查值是否在值列表中找到。例如 2 IN( 1, 2, 3 )
为 true。类似的函数 value NOT IN( list of values )
检查值是否不在值列表中找到。
# Railway stations in London or Paris
SELECT ?cityLabel ?station ?stationLabel ?location
WHERE {
?station wdt:P31 wd:Q55488. # is a railway station
?station wdt:P131* ?city.
?station wdt:P625 ?location
FILTER( ?city IN(wd:Q84, wd:Q90) ). # in London or Paris
SERVICE wikibase:label { bd:serviceParam wikibase:language "en,fr". }
}
isBLANK
[edit | edit source]isBLANK( variable )
表达式检查值是否为“未知值”。
#Demonstrates "unknown value" handling
SELECT ?human ?humanLabel
WHERE
{
?human wdt:P21 ?gender
FILTER isBLANK(?gender) .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
}
维基数据值也可以具有特殊值“无值”。对于普通三元组,这只会导致结果缺失。
# persons who were stateless (country of citizenship: no value) for some time (start time and end time qualifiers)
SELECT ?person ?personLabel ?start ?end
WHERE {
?person wdt:P31 wd:Q5;
p:P27 [
a wdno:P27; # no value for country of citizenship
pq:P580 ?start;
pq:P582 ?end
].
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
ORDER BY DESC(?end - ?start)
前缀 wdno:
选择“无值”节点。
代码 a
是一个特殊词。
字符串函数
[edit | edit source]STRLEN
[edit | edit source]STRLEN( string )
函数返回字符串的长度。例如,STRLEN(?name)
其中 ?name
为 "ABC" 将返回 3。
SUBSTR
[edit | edit source]SUBSTR( string, beginposition, stringlength )
函数返回字符串的子字符串,该子字符串从 beginposition 标记的位置开始,并且具有指示的长度。例如,SUBSTR( ?name,2,3 )
其中 ?name
= "ABCDEFGH" 将返回 "BCD"。没有长度的子字符串,例如 SUBSTR( ?name,2 )
将返回 "BCDEFGH"。
UCASE
[edit | edit source]UCASE( string )
函数返回大写字符串。例如,字符串 "Abc" 将返回为 "ABC"。
LCASE
[edit | edit source]LCASE( string )
函数返回小写字符串。例如,字符串 "Abc" 将返回为 "abc"。
STRSTARTS
[edit | edit source]STRSTARTS( string, comparestring )
函数检查字符串是否以比较字符串开头。例如,STRSTARTS( "ABCDEFGH", "ABC" )
返回 true,表示字符串以 "ABC" 开头。
STRENDS
[edit | edit source]STRENDS( string, comparestring )
函数检查字符串是否以比较字符串结尾。例如,STRENDS( "ABCDEFGH", "FGH" )
返回 true,表示字符串以 "FGH" 结尾。
CONTAINS
[edit | edit source]CONTAINS( string, comparestring )
函数检查字符串是否包含比较字符串。例如,CONTAINS( "ABCDEFGH", "DEF" )
返回 true,表示字符串包含 "DEF"。
STRBEFORE
[edit | edit source]STRBEFORE( string, comparestring )
函数返回比较字符串之前字符串的一部分。例如,STRBEFORE( "ABCDEFGH", "DEF" )
返回 "ABC"。如果未找到比较字符串,则返回 ""。
STRAFTER
[edit | edit source]STRAFTER( string, comparestring )
函数返回比较字符串之后字符串的一部分。例如,STRAFTER( "ABCDEFGH", "DEF" )
返回 "GH"。如果未找到比较字符串,则返回 ""。
ENCODE_FOR_URI
[edit | edit source]ENCODE_FOR_URI( string )
函数将字符串中的特殊字符转换为可在网络 URL 中使用的字符。例如,ENCODE_FOR_URI( "ABC DËFGH" )
返回 "ABC%20D%C3%8BFGH"。该函数的反函数是 wikibase:decodeUri( string )
。
CONCAT
[edit | edit source]CONCAT( string1, string2 ... )
函数返回两个或多个字符串的串联。例如,CONCAT( "ABCDEFGH", "XYZ" )
返回 "ABCDEFGHXYZ"。
LANGMATCHES
[edit | edit source]函数 LANGMATCHES( languagetag, languagerange )
检查语言标签是否与语言范围匹配。例如,这段代码 FILTER LANGMATCHES( LANG(?label), "fr" ).
筛选法语标签。它类似于 FILTER (LANG(?label) = "fr").
,区别在于 LANGMATCHES 过滤器还会输出带有区域的语言标签,例如 "fr-BE",而 (FILTER (LANG(?label) = "fr").
仅输出带有精确标签 "fr" 的字符串。语言范围为 "*" 匹配任何非空的语言标签字符串。
函数 REGEX( string, pattern, flag )
检查字符串是否与模式匹配。它主要用在 FILTER
子句中,例如 FILTER REGEX( string, pattern ).
。
模式可能包含不同的特殊字符。Blazegraph 实例(如 Wikidata 查询服务)将模式解释为 Java Pattern
,[1] 它是 ICU 正则表达式的子集。下表列出了最常见的特殊字符
|
|
|
flag 是可选的。flag "i" 表示匹配不区分大小写。
# Names of human settlements ending in "-ow" or "-itz" in Germany
#defaultView:Map
SELECT DISTINCT ?item ?itemLabel ?coord
WHERE
{
?item wdt:P31/wdt:P279* wd:Q486972; # instance/subclass of human settlement
wdt:P17 wd:Q183; # Germany
rdfs:label ?itemLabel;
wdt:P625 ?coord;
FILTER (LANG(?itemLabel) = "de").
FILTER REGEX (?itemLabel, "(ow|itz)$").
}
LIMIT 1000
示例
- 标题可能是押韵的
FILTER(REGEX(?title, "^\\w*(\\w{3})(\\W+\\w*\\1)+$", "i") && !REGEX(?title, "^(\\w+)(\\W+\\1)+$", "i")).
- 标题是头韵
FILTER(REGEX(STR(?title), "^(\\p{L})\\w+(?:\\W+\\1\\w+){2,}$", "i")).
PS:单个 \ 用作字符串中的转义符号,因此 \\ 用于表示单个 \。
函数 REPLACE( string, pattern, replacement, flag )
在将 string
中所有出现的 pattern
替换为 replacement
后返回字符串。pattern
的解释方式与 REGEX
中相同。replacement
可以包含 $n
或 ${name}
,它们将被模式中相应的编号或命名捕获组 替换。[1] 可选的 flag
会影响正则表达式模式,就像 REGEX()
的 flag
参数一样。例如,REPLACE( "ABCDEFGH", "DEF", "_def_" )
返回 "ABC_def_GH"。REPLACE( "ABCDEFGH", "[AEIOU]", "" )
从原始字符串中删除所有元音。
函数 ABS( number )
返回数字的绝对值。例如,ABS( -1 )
返回 1。
函数 ROUND( number )
返回数字的四舍五入值。例如,ROUND( 1.4 )
返回 1,而 ROUND( 1.6 )
返回 2。
函数 CEIL( number )
返回最大的数字(向上取整)。例如,CEIL( 1.4 )
和 CEIL( 1.6 )
都返回 2。
函数 FLOOR( number )
返回最小的数字(向下取整)。例如,FLOOR( 1.4 )
和 FLOOR( 1.6 )
都返回 1。
函数 RAND( )
返回 0 到 1 之间的随机值。例如,RAND( )
返回 0.7156405780739334。
函数 COUNT
、MIN
、MAX
、AVG
和 SUM
只能用作 聚合函数。
# average age of painters by century
SELECT ?century (AVG(?age) AS ?average_age) (ROUND(AVG(?age)) AS ?rounded_average_age)
WHERE
{
?item wdt:P31 wd:Q5. # is a human
?item wdt:P106 wd:Q1028181. # occupation painter
?item wdt:P569 ?born.
?item wdt:P570 ?died.
FILTER( ?died > ?born ).
BIND( (?died - ?born)/365.2425 AS ?age )
BIND( FLOOR(YEAR(?born)/100)*100 AS ?century )
}
GROUP BY ?century
ORDER BY ?century
例如,BIND( MAX( ?var1, ?var2 ) AS ?max)
不起作用。相反,请使用表达式 BIND( IF( ?var1>?var2, ?var1, ?var2 ) AS ?max)
。
函数 NOW( )
返回当前日期和时间。
使用 NOW() + "P1D"^^xsd:duration
之类的结构,可以从当前日期添加或减去天数。
NOW() + "P1M"^^xsd:duration
将添加 1 个月。
NOW() + "P1Y"^^xsd:duration
将添加 1 年。
您可以使用 "P1Y1M1DT0H0M0.000S"^^xsd:duration
添加或减去任何组合的年、月、日,甚至小时、分钟和秒。
函数 YEAR( datevalue )
返回日期值的年份。函数 MONTH
和 DAY
返回月份或日期。
函数 HOURS( datevalue )
返回日期值的小时。函数 MINUTES
和 SECONDS
返回分钟或秒。
目前 Wikidata 不以小时、分钟或秒的形式保存日期值。
函数 TIMEZONE( datevalue )
返回日期值的时区。目前在 Wikidata 中,所有日期的 TIMEZONE
都是 "PT0S",表示 UTC。其他有效值介于 -PT14H 和 PT14H 之间,表示以小时为单位的时区偏移量。
函数 TZ( datevalue )
返回日期值的时区,以简单的文字形式表示。目前在 Wikidata 中,所有日期的 TZ
都是 "Z",表示 UTC。
日期示例
# Query to find all musicians who have already died
# calculate their age (full years) at death
# count how many of them died at each age
#defaultView:LineChart
SELECT ?age (COUNT (DISTINCT ?a) AS ?count)
WHERE {
?a wdt:P31 wd:Q5. #instance of human
?a wdt:P106/wdt:P279 wd:Q639669. #occupation a subclass of musician
?a p:P569/psv:P569 ?birth_date_node.
?a p:P570/psv:P570 ?death_date_node.
?birth_date_node wikibase:timeValue ?birth_date.
?death_date_node wikibase:timeValue ?death_date.
BIND( YEAR(?death_date) - YEAR(?birth_date) -
IF(MONTH(?death_date)<MONTH(?birth_date) ||
(MONTH(?death_date)=MONTH(?birth_date) && DAY(?death_date)<DAY(?birth_date)),1,0) AS ?age )
# calculate the age, precisely to the day (times and timezones ignored)
FILTER(?age > 10 && ?age < 100). #ignore outliers, several of which are probably errors
}
GROUP BY ?age
ORDER BY ?age
函数 geof:distance
返回两点之间的距离,以公里为单位。
使用示例
# distance between 2 cities
SELECT ?city1 ?city1Label ?location1 ?city2 ?city2Label ?location2 ?dist
WHERE
{
VALUES ?city1 { wd:Q84 }. # London
VALUES ?city2 { wd:Q90 }. # Paris
?city1 wdt:P625 ?location1.
?city2 wdt:P625 ?location2.
BIND(geof:distance(?location1, ?location2) as ?dist)
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
函数 geof:longitude
和 geof:latitude
将一个 Well-Known Text 文字 (<http://www.opengis.net/ont/geosparql#wktLiteral>) 的点几何分别转换为它的经度和纬度。
使用示例
# Museums in Barcelona with coordinates
SELECT ?item ?itemLabel ?coord ?lon ?lat
WHERE
{
?item wdt:P131 wd:Q1492; # in the administrative territory of Barcelona
wdt:P31 wd:Q33506; # is a museum
wdt:P625 ?coord.
BIND(geof:longitude(?coord) AS ?lon)
BIND(geof:latitude(?coord) AS ?lat)
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
也可以使用 wikibase:geoLongitude
和 wikibase:geoLatitude
限定符来检索坐标节点的经度和纬度。有关解释,请参见 此处。
# Museums in Barcelona with coordinates
SELECT ?item ?itemLabel ?coord ?lon ?lat
WHERE
{
?item wdt:P131 wd:Q1492; # in the administrative territory of Barcelona
wdt:P31 wd:Q33506; # is a museum
p:P625 [
ps:P625 ?coord;
psv:P625 [
wikibase:geoLongitude ?lon;
wikibase:geoLatitude ?lat;
]
].
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
代码 BIND("[AUTO_COORDINATES]" as ?loc)
会返回当前位置,如果您允许浏览器使用它。
# Drinking establishments near me
SELECT DISTINCT ?pub ?pubLabel ?dist
WHERE
{
BIND("[AUTO_COORDINATES]" as ?loc) .
SERVICE wikibase:around {
?pub wdt:P625 ?location .
bd:serviceParam wikibase:center ?loc.
bd:serviceParam wikibase:radius "1" .
}
FILTER EXISTS { ?pub wdt:P31/wdt:P279* wd:Q5307737 }
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
BIND(geof:distance(?loc, ?location) as ?dist)
} ORDER BY ?dist
有关 COUNT、MIN、MAX、SUM、AVG、SAMPLE 和 GROUP_CONCAT,请参见 聚合函数
- ↑ a b Wikidata 查询服务使用 Blazegraph 的一个 Wikimedia 分支,它 依赖于 OpenJDK 8。其他实例可能运行不同版本的 Java,其 Unicode 支持级别也不同。