SPARQL strlen显示xs:date的值不正确

时间:2014-03-04 20:06:44

标签: rdf sparql dbpedia

方案

我正在使用开源的dbpedia浏览器来处理sparql查询。我试图从ds:birthDate的xs:date中解析月和日值。它不是dateTime所以我不能使用month()或dayOfWeek()函数。我转而使用substr,它可以完美地运行一个月。但是,尝试使用值9,2进行子字符串会给出无效的索引错误。所以我修改了sparql以显示字符串和strlen值,现在我完全糊涂了。它显示的字符串是一个有效的日期格式“yyyy-mm-dd”,它是10个字符。但是,它显示了一个7的strlen。

以下是查询:

PREFIX dbo: <http://dbpedia.org/ontology/>

SELECT ?name, ?bmonth, ?bstring, ?len1, ?len2
WHERE {
  ?person foaf:name ?name .
  ?person dbo:birthDate ?birth .
  BIND (str(?birth) AS ?bstring)
  BIND (strlen(?bstring) AS ?len1)
  BIND (substr(?bstring, 6,2) AS ?bmonth)
  BIND (strlen(?bstring) AS ?len2)
  FILTER ( ?bmonth = '12' )
} GROUP BY ?person ORDER BY ?len1 LIMIT 50

以下是几行结果:

name            bmonth  bstring        len1 len2
"Ann Ronell"@e  "12"    "1906-12-28"    7   7
"Anna Freud"@en "12"    "1895-12-03"    7   7
"Dorothy Lamour"@en "12"    "1914-12-10"    7   7
"Doug Mohns"@en "12"    "1933-12-13"    7   7

查询:http://tinyurl.com/k6kuapd

结论/问题

基本上,我真的只是想从字符串中获取dayOfMonth值。但是,如果有人也可以向我解释它是如何提出的7我真的很感激它!

1 个答案:

答案 0 :(得分:4)

通过强制转换为xsd:dateTime

来提取日期和月份

SPARQL 1.1有一个day函数,它返回dateTime的日期。

  

17.4.5.4 day

xsd:integer  DAY (xsd:dateTime arg)
     

以整数形式返回arg的日期部分。

     

此功能对应fn:day-from-dateTime

day("2011-01-10T14:45:13.815-05:00"^^xsd:dateTime)
=> 10

您可以使用xsd:dateTime作为功能将xsd:date转换为可以应用此功能的dateTimes。举个例子:

prefix xsd: <http://www.w3.org/2001/XMLSchema#>

select ?month ?day where {
  # Provide some values for ?date.  Note that 
  # we can use xsd:date *and* xsd:dateTime here,
  # as both can be cast to xsd:dateTime.
  values ?date { 
    "2011-01-02"^^xsd:date
    "2012-10-11"^^xsd:date
    "2013-12-30T14:45:13.815-05:00"^^xsd:dateTime 
  }

  # Cast to a xsd:dateTime and extract the day and month.
  bind( day(xsd:dateTime(?date)) as ?day )
  bind( month(xsd:dateTime(?date)) as ?month )
}
---------------
| month | day |
===============
| 01    | 02  |
| 10    | 11  |
| 12    | 30  |
---------------

为什么DBpedia会做一些奇怪的事情

最简单的方法是找出长度 7的值,并且看看你得到了什么。例如,看看

的结果
SELECT ?person ?birth WHERE {
  ?person dbpedia-owl:birthDate ?birth .
  bind( strlen(str(?birth)) as ?blen )
  filter( ?blen < 10 )
}
LIMIT 25

SPARQL results

Person                            Birth
-----------------------------------------------------------------------------------------
Alyson_No%C3%ABl                  "--12-03"^^<http://www.w3.org/2001/XMLSchema#gMonthDay>
Corneille_(singer)                "--03-24"^^<http://www.w3.org/2001/XMLSchema#gMonthDay>
Count_Karl_Sigmund_von_Hohenwart  "--02-12"^^<http://www.w3.org/2001/XMLSchema#gMonthDay>
David_Lewis_(politician)          "--06-23"^^<http://www.w3.org/2001/XMLSchema#gMonthDay>
…                                 …

有些值不是xsd:dateTimesxsd:date s,而是xsd:gMonthDay s。这些没有指定年份,因此字符串不像xsd:date那样长。这是另一个原因,说明为什么你应该转换为xsd:date(或检查数据类型等,因为你不能从xsd:gMonthDay转换为xsd:dateTime

正如评论中指出的那样,您的查询实际上并不合法。您应该无法选择未分组的变量,因此或许正在发生的事情是,当您完成时

SELECT ?name, ?bmonth, ?bstring, ?len1, ?len2 WHERE {
  ?person foaf:name ?name .
  ?person dbo:birthDate ?birth .
  BIND (str(?birth) AS ?bstring)
  BIND (strlen(?bstring) AS ?len1)
  BIND (substr(?bstring, 6,2) AS ?bmonth)
  BIND (strlen(?bstring) AS ?len2)
  FILTER ( ?bmonth = '12' )
}
GROUP BY ?person
ORDER BY ?len1
LIMIT 50

您获得了一些DBpedia特定的行为。例如,也许你是按人分组,然后选择是做一个隐含的sample,也许这些人中有一些人的出生日期有多个值。 (我不确定这一点,这只是我发生的一种可能性。目前DBpedia正在进行维护,因此我无法检查那里有哪些数据,即使我可以,这也是标准未定义的行为我建议您在sparql.org's query validator检查您的查询并首先获得合法的SPARQL。只有这样我们才能判断您是否返回它应该的内容。)