【问题标题】:Syntax for nested IF statements in SPARQLSPARQL 中嵌套 IF 语句的语法
【发布时间】:2015-12-14 06:02:30
【问题描述】:

我正在尝试运行以下 SPARQL 查询,但它一直返回 SR171: Transaction timed out

SELECT ?isBusAvailable WHERE {
  SELECT DISTINCT IF (
  (
  SELECT ?value2 WHERE {
      GRAPH data: { ?obsValueID2 ontology:value ?value2 }
      GRAPH data: { ?obsValueID2 rdf:label "Availability" }
      GRAPH data: { ?obsValueID2 ontology:isObservedValueOf ?obsID2}
      GRAPH data: { ?obsID2 ssn:observationResultTime ?time2 }
      GRAPH data: { ?obsID2 ssn:observedBy ?id2 }
      GRAPH meta: { ?id2 rdf:label "MyBusService" } 
  } ORDER BY DESC (?time2) LIMIT 1) > 1, "Take Bus", (
                       SELECT ?isBikeAvailable WHERE {
                       SELECT DISTINCT IF (
                       (
                       SELECT ?value3 WHERE {
                            GRAPH data: { ?obsValueID3 ontology:value ?value3 }
                            GRAPH data: { ?obsValueID3 rdf:label "Availability" }
                            GRAPH data: { ?obsValueID3 ontology:isObservedValueOf ?obsID3}
                            GRAPH data: { ?obsID3 ssn:observationResultTime ?time3 }
                            GRAPH data: { ?obsID3 ssn:observedBy ?id3 }
                            GRAPH meta: { ?id3 rdf:label "MyBikeService" } 
                       } ORDER BY DESC (?time3) LIMIT 1
                       ) > 0, "Take Bike", "Take Taxi") as ?isBikeAvailable WHERE { ?1 ?2 ?3}})) as ?isBusAvailable WHERE { ?4 ?5 ?6}}

如果我单独运行它们,它会在 1 秒内运行。以下示例有效。

SELECT ?isBusAvailable WHERE {
  SELECT DISTINCT IF (
  (
  SELECT ?value2 WHERE {
      GRAPH data: { ?obsValueID2 ontology:value ?value2 }
      GRAPH data: { ?obsValueID2 rdf:label "Availability" }
      GRAPH data: { ?obsValueID2 ontology:isObservedValueOf ?obsID2}
      GRAPH data: { ?obsID2 ssn:observationResultTime ?time2 }
      GRAPH data: { ?obsID2 ssn:observedBy ?id2 }
      GRAPH meta: { ?id2 rdf:label "MyBusService" } 
  } ORDER BY DESC (?time2) LIMIT 1) > 1, "Take Bus", 'Take Bike') as ?isBusAvailable WHERE { ?4 ?5 ?6}} 

如果第一次查询的结果为真,则返回'Take Bus';否则,运行第二个查询,并返回“Take Bike”或“Take Taxi”。

显然问题出在第二个查询上(来自第一个查询的错误条件)。在“乘坐巴士”之后,如果我将第二个查询更改为“乘坐自行车”,它就会起作用。

【问题讨论】:

  • 根据sparql.org's query validator,这(无论执行多长时间)不是合法的 SPARQL 查询。这可能适用于您发布的答案。您是否考虑过重新定位查询?
  • 没错。此问题中发布的查询语法不正确。这就是我的问题。我发布的答案中的查询有效。你能告诉我你所说的“重新定相”是什么意思吗?另外,请改进我发布的答案。
  • 我的意思是,即使某些 SPARQL 引擎接受它,您答案中的语法也不是合法的 SPARQL 语法。例如,select distinct if( ... ) 不是合法的 SPARQL。换句话说,我的意思是您应该考虑重组您的 SPARQL 查询,使其合法。一旦它是合法的,我们可以帮助它提高性能。此外,如果您能告诉我们查询试图完成什么以及数据是什么样的,这将有所帮助。 看起来查询可以写得更简单,但很难说,因为我们不知道它应该做什么。
  • 我有两个服务:BusService 和 BikeService。该查询正在尝试检索总线的“可用”属性。如果有公共汽车,它将返回“Take Bus”。如果公共汽车不可用,请检查是否有可用的自行车。如果有可用的自行车返回“Take Bike”,否则返回“Take Taxi”。基本上,我有 2 个图表。一种是服务的元数据(即元数据:),另一种包含服务产生的数据(即示例中的数据:)。它从元数据中选择服务的 id 并检查数据图中的最后一个读数。
  • 给定服务名称和我感兴趣的属性(例如,可用性),我想检索该服务的最后读数。根据返回的值,我想做出一些决定,如上所述。

标签: rdf sparql virtuoso


【解决方案1】:

false 条件下的查询需要尊重 SPARQL 中 IF 条件语句的格式,因为它返回一个值。删除“SELECT DISTINCT”

SELECT ?isBusAvailable WHERE { 
  SELECT DISTINCT (IF(
        (
         SELECT ?value WHERE {
                GRAPH data: { ?obsValueID ontology:value ?value }
                GRAPH data: { ?obsValueID rdf:label "Availability" }
                GRAPH data: { ?obsValueID ontology:isObservedValueOf ?obsID}
                GRAPH data: { ?obsID ssn:observationResultTime ?time }
                GRAPH data: { ?obsID ssn:observedBy ?id }
                GRAPH meta: { ?id rdf:label "MyBusService" } 
        } ORDER BY DESC (?time) LIMIT 1) > 0,'Take Bus', (

                       IF (
                       (
                       SELECT ?value WHERE {
                            GRAPH data: { ?obsValueID ontology:value ?value }
                            GRAPH data: { ?obsValueID rdf:label "Availability" }
                            GRAPH data: { ?obsValueID ontology:isObservedValueOf ?obsID}
                            GRAPH data: { ?obsID ssn:observationResultTime ?time }
                            GRAPH data: { ?obsID ssn:observedBy ?id }
                            GRAPH meta: { ?id rdf:label "MyBikeService" } 
                       } ORDER BY DESC (?time) LIMIT 1
                       ) > 0, "Take Bike", "Take Taxi")
                       )) AS ?isBusAvailable) FROM data: WHERE { ?1 ?2 ?3 }}

编辑: select distinct if( ... ) 不是合法的 SPARQL,因此 if 语句需要用括号括起来。查询变为:select distinct (if( ... ))

【讨论】:

  • 我不明白您在此查询之前添加的符号......并且进一步无法判断这是否是对您原始问题的回答,还是作为后续问题。如果有后续,最好编辑问题以包含此信息,希望表达得更清楚(然后删除此答案)。
  • 这是我的答案,也是有效的查询。我用virtuoso.openlinksw.com/dataspace/doc/dav/wiki/Main/VOSSPARQL
【解决方案2】:

@andrei -- 我认为您的 ?isBusAvailable 很容易混淆 -- 考虑到您最终返回的文字值,这可能会更好 ?travelMethod

当我阅读内容时,这里的问题实际上是如何正确构造嵌套的IFs——问题的标题可能应该是“在 SPARQL 中嵌套 IF 语句的正确语法是什么?”

在简单的流程中,我认为您正在做的是检查可用的巴士,如果存在则返回“乘坐巴士”;如果没有,您检查是否有可用的自行车,如果存在则返回“Take bike”;如果没有,您返回“乘坐出租车”。在伪代码中,IF AVAIL bus, THEN take bus, ELSE ( IF AVAIL bike, THEN take bike, ELSE take taxi ).

@joshua-taylor 在一件事上是对的——SELECT DISTINCT IF (…) 不是严格有效的,但修复只是一个额外的括号包装器——例如,以下是有效的(并验证)——

SELECT DISTINCT ( IF ( ( 1 = 1 ) 
                     , "true" 
                     , "false" 
                     )           AS ?test ) 
WHERE { ?x ?y ?z } 
LIMIT 1

但在您的查询中修复此问题并不会从验证器中获得任何更好的输出。事实上,用1 替换内部的(SELECT ?value … LIMIT 1) 查询可以使整个大型查询生效——

SELECT ?travelMethod 
   WHERE 
     { 
        SELECT DISTINCT 
                         ( IF 
                               (
                                  (
                                     1  > 0
                                  )
                               ,  "Take Bus"
                               ,  (
                                        IF (
                                              (
                                                 1  > 0
                                              )
                                           ,  "Take Bike"
                                           ,  "Take Taxi"
                                           )
                                  )
                               )  AS  ?travelMethod
                         ) 
        FROM         data: 
        WHERE        { ?1  ?2  ?3 }
     }

-- 并且那些内部 (SELECT ?value … LIMIT 1) 查询也可以自行验证--

SELECT    ?value 
WHERE     
          {
             GRAPH data: { ?obsValueID  ontology:value              ?value          }
             GRAPH data: { ?obsValueID  rdf:label                   "Availability"  }
             GRAPH data: { ?obsValueID  ontology:isObservedValueOf  ?obsID          }
             GRAPH data: { ?obsID       ssn:observationResultTime   ?time           }
             GRAPH data: { ?obsID       ssn:observedBy              ?id             }
             GRAPH meta: { ?id          rdf:label                   "MyBusService"  } 
          }  
ORDER BY  DESC (?time) 
LIMIT     1

我相信以下是有效的语法——即使 sparql.org 验证器阻塞它——但我不能确定它是否执行,因为我没有时间重新调整查询以针对随机端点运行和数据集。如果您重新编写查询以针对例如 DBpedia 运行,您可以帮助下一个人!

SELECT ?travelMethod 
   WHERE 
     { 
        SELECT DISTINCT 
                         ( IF 
                               (
                                  (
                                     (  SELECT    ?value 
                                        WHERE     
                                                  {
                                                     GRAPH data: { ?obsValueID  ontology:value              ?value          }
                                                     GRAPH data: { ?obsValueID  rdf:label                   "Availability"  }
                                                     GRAPH data: { ?obsValueID  ontology:isObservedValueOf  ?obsID          }
                                                     GRAPH data: { ?obsID       ssn:observationResultTime   ?time           }
                                                     GRAPH data: { ?obsID       ssn:observedBy              ?id             }
                                                     GRAPH meta: { ?id          rdf:label                   "MyBusService"  } 
                                                  }  
                                        ORDER BY  DESC (?time) 
                                        LIMIT     1
                                     )  > 0
                                  )
                               ,  "Take Bus"
                               ,  (
                                        IF (
                                              (
                                                 (  SELECT    ?value 
                                                    WHERE
                                                              {
                                                                 GRAPH data: { ?obsValueID  ontology:value              ?value           }
                                                                 GRAPH data: { ?obsValueID  rdf:label                   "Availability"   }
                                                                 GRAPH data: { ?obsValueID  ontology:isObservedValueOf  ?obsID           }
                                                                 GRAPH data: { ?obsID       ssn:observationResultTime   ?time            }
                                                                 GRAPH data: { ?obsID       ssn:observedBy              ?id              }
                                                                 GRAPH meta: { ?id          rdf:label                   "MyBikeService"  } 
                                                              } 
                                                    ORDER BY  DESC (?time) 
                                                    LIMIT     1
                                                 )  > 0
                                              )
                                           ,  "Take Bike"
                                           ,  "Take Taxi"
                                           )
                                  )
                               )  AS  ?travelMethod
                         ) 
        FROM         data: 
        WHERE        { ?1  ?2  ?3 }
     }

花了一点时间离开它,并重新阅读您在上面的 cmets 中对您的数据所说的内容,我可以进一步细化这个查询,这也可能使其执行得更快 --

SELECT ?travelMethod 
   WHERE 
     { 
        SELECT DISTINCT 
                         ( IF 
                               (
                                  (
                                     (  SELECT    ?value 
                                        WHERE     
                                                  {
                                                     GRAPH data: { ?obsValueID  ontology:value              ?value
                                                                             ;  rdf:label                   "Availability"
                                                                             ;  ontology:isObservedValueOf  ?obsID
                                                                 . ?obsID       ssn:observationResultTime   ?time
                                                                             ;  ssn:observedBy              ?id
                                                                 }
                                                     GRAPH meta: { ?id          rdf:label                   "MyBusService"  } 
                                                  }  
                                        ORDER BY  DESC (?time) 
                                        LIMIT     1
                                     )  > 0
                                  )
                               ,  "Take Bus"
                               ,  (
                                        IF (
                                              (
                                                 (  SELECT    ?value 
                                                    WHERE
                                                              {
                                                                 GRAPH data: { ?obsValueID  ontology:value              ?value
                                                                                         ;  rdf:label                   "Availability"
                                                                                         ;  ontology:isObservedValueOf  ?obsID
                                                                             . ?obsID       ssn:observationResultTime   ?time
                                                                                         ;  ssn:observedBy              ?id
                                                                             }
                                                                 GRAPH meta: { ?id          rdf:label                   "MyBikeService"  } 
                                                              } 
                                                    ORDER BY  DESC (?time) 
                                                    LIMIT     1
                                                 )  > 0
                                              )
                                           ,  "Take Bike"
                                           ,  "Take Taxi"
                                           )
                                  )
                               )  AS  ?travelMethod
                         ) 
        FROM         data: 
        WHERE        { ?1  ?2  ?3 }
     }

【讨论】:

  • 这与我的回答有何不同?
  • 虽然你的可能被某些端点成功执行,但它不是有效的 SPARQL,所以成功有点像赌博。此外,我详细说明了正在发生的事情——我改变了什么以及为什么。我希望用我的额外空格让它更清楚。修剪这些空格和换行符,您的查询开始 SELECT ?isBusAvailable WHERE { SELECT DISTINCT IF ( ( SELECT ?value WHERE 而我的查询是 SELECT ?travelMethod WHERE { SELECT DISTINCT ( IF ( ( ( SELECT ?value WHERE - SPARQL 1.1 语法需要我添加的括号(IF 之前的一个和第二个 SELECT 之前的一个)。
  • 我测试了这个查询并且它有效。同样,与我的答案的唯一区别是将 if 语句包装成括号。此外,添加分号和点会使查询在 sparql 中不是很直观。你能在你的回答中解释为什么你认为这会跑得更快吗?另外,我假设分号是用来避免重复的,但是 "?obsID" 之前的点的目的是什么?
  • 我用 2 替换了 5 个句子——一个包含 2 个关于 ?obsID 的谓词,一个包含 3 个关于 obsValueID 的谓词。更详细地说——你有 5 个对 data: 图表的引用,每个都是一个单独的四边形,包裹在 { } 中,我将这些单独引用到了带有 5 个三元组的 data: 图表。这可能会加快速度(取决于处理引擎),因为引擎可能会加载/处理此图一次而不是 5 次。其中,分号只是减少查询字符串长度的语法糖(当填充空白被删除时)。该点被它替换的} 所暗示。
  • 另外请注意,我添加了第二个括号包裹——IF 构造中的完整“测试”表达式被包裹在括号中——IF ( ( test1 = test2 ) , "true" , "false" )。你有IF ( ( SELECT ?value … LIMIT 1 ) > 0 , "Take Bike" , "Take Taxi" )。我有IF ( ( ( SELECT ?value … LIMIT 1 ) > 0 ) , "Take Bike" , "Take Taxi" )。我知道这些很难看到;我希望我的缩进和填充有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-01
  • 2018-12-06
  • 1970-01-01
相关资源
最近更新 更多