代码之家  ›  专栏  ›  技术社区  ›  Pietro Maria Liuzzo

SPARQL按文字的数字部分排序

  •  1
  • Pietro Maria Liuzzo  · 技术社区  · 7 年前

    如何仅使用文本值中的数字对SPARQL查询的结果排序?

    我有一个返回变量的查询?可以包含以下文字值的locasfrom

    • 1.
    • 21r
    • 33伏
    • 45ra
    • 156vb

    我想使用ORDER BY,并像上面那样对结果进行排序,只使用数字部分,忽略字母。

    我试过了

    SELECT ?locusFrom ?locusTo ?locusTarget ?uniCont1
    WHERE {
    bm:BNFet45 dcterms:hasPart ?uniProd .
    ?uniProd a SdC:UniProd .
    ?uniProd dcterms:hasPart ?uniCont .
    ?uniCont a SdC:UniCont .
    ?uniCont dcterms:hasPart ?uniCont1 .
    ?uniCont1 a SdC:UniCont ;
                bm:hasLocus ?locus .
                OPTIONAL{?locus bm:locusTarget ?locusTarget}
                OPTIONAL{?locus bm:locusFrom ?locusFrom}
                OPTIONAL{?locus bm:locusTo ?locusTo}
    BIND( (STRBEFORE(?locusFrom,"r") || STRBEFORE(?locusFrom,"v") ) as ?substring )
    }
    ORDER BY ?substring
    

    并返回此结果(缩短)

    <sr:sparql xmlns:sr="http://www.w3.org/2005/sparql-results#">
    <sr:head>
    <sr:variable name="locusFrom"/>
    <sr:variable name="locusTo"/>
    <sr:variable name="locusTarget"/>
    <sr:variable name="uniCont1"/>
    </sr:head>
    <sr:results>
    <sr:result>
    <sr:binding name="locusTarget">
    <sr:literal>12</sr:literal>
    </sr:binding>
    <sr:binding name="uniCont1">
    <sr:uri>http://betamasaheft.eu/BNFet45/msitem/f2_i1.1</sr:uri>
    </sr:binding>
    </sr:result>
    <sr:result>
    <sr:binding name="locusFrom">
    <sr:literal>1r</sr:literal>
    </sr:binding>
    <sr:binding name="uniCont1">
    <sr:uri>http://betamasaheft.eu/BNFet45/msitem/p1_i1.1</sr:uri>
    </sr:binding>
    </sr:result>
    <sr:result>
    <sr:binding name="locusFrom">
    <sr:literal>18v</sr:literal>
    </sr:binding>
    <sr:binding name="uniCont1">
    <sr:uri>http://betamasaheft.eu/BNFet45/msitem/p1_i1.2</sr:uri>
    </sr:binding>
    </sr:result>
    <sr:result>
    <sr:binding name="locusFrom">
    <sr:literal>53r</sr:literal>
    </sr:binding>
    <sr:binding name="uniCont1">
    <sr:uri>http://betamasaheft.eu/BNFet45/msitem/p1_i1.3</sr:uri>
    </sr:binding>
    </sr:result>
    <sr:result>
    <sr:binding name="locusFrom">
    <sr:literal>17r</sr:literal>
    </sr:binding>
    <sr:binding name="locusTo">
    <sr:literal>17v</sr:literal>
    </sr:binding>
    <sr:binding name="uniCont1">
    <sr:uri>http://betamasaheft.eu/BNFet45/msitem/f2_i1.4</sr:uri>
    </sr:binding>
    </sr:result>
    <sr:result>
    <sr:binding name="locusFrom">
    <sr:literal>18r</sr:literal>
    </sr:binding>
    <sr:binding name="locusTo">
    <sr:literal>23r</sr:literal>
    </sr:binding>
    <sr:binding name="uniCont1">
    <sr:uri>http://betamasaheft.eu/BNFet45/msitem/f2_i1.5</sr:uri>
    </sr:binding>
    </sr:result>
    </sr:results>
    </sr:sparql>
    

    在我看来,在第一组之后,它又开始计数了。 我如何才能将其全部排序? 非常感谢!

    1 回复  |  直到 7 年前
        1
  •  3
  •   Stanislav Kralin kenwenzel    7 年前

    大体上 REPLACE 接受XPath样式的正则表达式作为其第二个参数。然而,自 ?locusFrom 约束在 OPTIONAL ,您可能还需要 COALESCE

    SELECT * {
       VALUES (?locusFrom) {
           (UNDEF)
           ("")
           ("1")
           ("156vb")
           ("21r")
           ("33vu")
           ("45ra")
           ("ab")
       }
       BIND (xsd:integer(REPLACE(?locusFrom, "\\D+", "")) AS ?number1)
       BIND (COALESCE(?number1, 0) AS ?number2)
    } ORDER BY ?number2