Запретить GROUP_CONCAT возвращать пустую строку, когда сгруппированные результаты равны нулю в SPARQL - PullRequest
2 голосов
/ 29 мая 2020

У меня есть запрос SPARQL, который возвращает то, что я хочу, за исключением одного. Когда я использую GROUP_CONCAT, я получаю в результате пустую строку. Я хотел бы, чтобы в возвращаемом наборе было просто null, когда группируются значения null. В моем примере ниже вы можете увидеть, что мои ?team результаты возвращают "" вместо того, чтобы просто null, например, ?end возвращается. В случае пустой строки мои значения ?person на самом деле равны null. Есть ли способ заставить ?team вернуть null?

Запрос SPARQL:

SELECT ?event ?start ?end ?team {
    SELECT ?event ?start ?end (GROUP_CONCAT(DISTINCT ?person;SEPARATOR=",") AS ?team) {
        ?event a cls:Event ;
            prop:startDate ?start .

        OPTIONAL {
            ?event prop:endDate ?end .
            ?event prop:teamMember ?person .
        }

        FILTER (?start >= "2020-05-25" && ?start < "2020-08-31")
    } GROUP BY ?event ?start ?end
} ORDER BY ?start

Результаты:

| event       | start      | end        | team                                                         |
|-------------|------------|------------|--------------------------------------------------------------|
| event:Test1 | 2020-05-27 |            | ""                                                           |
| event:Test3 | 2020-05-28 | 2020-05-29 | "http://foo.bar/person/smith,http://foo.bar/person/williams" |
| event:Test2 | 2020-05-29 |            | ""                                                           |

1 Ответ

3 голосов
/ 29 мая 2020

Боюсь, что спецификация SPARQL (см. здесь ) подтверждает то, что вы наблюдаете как правильное поведение.

Чтобы понять, почему это так, представьте, что вместо выполнения GROUP_CONCAT, вы делали COUNT. Тогда вы, если в команде нет участников, вы хотели бы видеть 0, а не null.

Чтобы получить то, что вы хотите, я бы попробовал это в качестве первой итерации:

SELECT ?event ?start ?end ?team {

    BIND(IF(?team_temp = "", ?team_temp, ?unboundVariable) AS ?team)
#The above check if ?team_temp = "". If it is not, then there is a team and you use ?team-temp as ?team. Otherwise, if ?team_temp = "", you use some unbound variable as ?team, and this unbound variable will be null.

    {SELECT ?event ?start ?end (GROUP_CONCAT(DISTINCT ?person;SEPARATOR=",") AS ?team_temp) {
            ?event a cls:Event ;
                prop:startDate ?start .

            OPTIONAL { ?event prop:endDate ?end }
            OPTIONAL { ?event prop:teamMember ?person }
#Notice that if we want to match ?end and ?person optionally AND independently, then we need two optional statements above here, instead of one large one.

            FILTER (?start >= "2020-05-25" && ?start < "2020-08-31")
        } GROUP BY ?event ?start ?end}
    } ORDER BY ?start
...