'SPARQL: Variable must be included in group by clause
For every sosa:FeatureOfInterest
(room), get the lowest temperature per day from the associated sensors for that room. There are 100 rooms. Each room has 3 sensors. The timeframe is one year.
Goal: Query to select lowest temperature per day per room from group of sensors plus time of day when the temperature occurred.
Example data (N3):
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix sosa: <http://www.w3.org/ns/sosa/>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
prefix ex: <http://www.example.com/>
# Room FOIs
ex:room1Foi a sosa:FeatureOfInterest .
# ...
ex:room100Foi a sosa:FeatureOfInterest .
# Room 1 sensor observations 1/1/2021
ex:obs1Room1 a sosa:Observation .
sosa:hasFeatureOfInterest ex:room1Foi ;
sosa:resultTime "2021-01-01T00:00:00"^^xsd:dateTime ;
sosa:observedProperty "TEMP"^^xsd:string ;
sosa:hasSimpleResult "51.4"^^xsd:decimal .
ex:obs2Room1 a sosa:Observation .
sosa:hasFeatureOfInterest ex:room1Foi .
sosa:resultTime "2021-01-01T08:00:00"^^xsd:dateTime ;
sosa:observedProperty "TEMP"^^xsd:string ;
sosa:hasSimpleResult "50.2"^^xsd:decimal .
ex:obs3Room1 a sosa:Observation .
sosa:hasFeatureOfInterest ex:room1Foi .
sosa:resultTime "2021-01-01T:16:00"^^xsd:dateTime ;
sosa:observedProperty "TEMP"^^xsd:string ;
sosa:hasSimpleResult "49.8"^^xsd:decimal .
# Room 1 sensor observations 1/2/2021
ex:obs4Room1 a sosa:Observation .
sosa:hasFeatureOfInterest ex:room1Foi ;
sosa:resultTime "2021-01-02T00:00:00"^^xsd:dateTime ;
sosa:observedProperty "TEMP"^^xsd:string ;
sosa:hasSimpleResult "61.4"^^xsd:decimal .
ex:obs5Room1 a sosa:Observation .
sosa:hasFeatureOfInterest ex:room1Foi .
sosa:resultTime "2021-01-02T08:00:00"^^xsd:dateTime ;
sosa:observedProperty "TEMP"^^xsd:string ;
sosa:hasSimpleResult "60.2"^^xsd:decimal .
ex:obs6Room1 a sosa:Observation .
sosa:hasFeatureOfInterest ex:room1Foi .
sosa:resultTime "2021-01-02T:16:00"^^xsd:dateTime ;
sosa:observedProperty "TEMP"^^xsd:string ;
sosa:hasSimpleResult "59.8"^^xsd:decimal .
# ...
# Room 100 sensor observations 1/1/2021
ex:obs1Room100 a sosa:Observation .
sosa:hasFeatureOfInterest ex:room100Foi ;
sosa:resultTime "2021-01-01T00:00:00"^^xsd:dateTime ;
sosa:observedProperty "TEMP"^^xsd:string ;
sosa:hasSimpleResult "50.7"^^xsd:decimal .
ex:obs2Room100 a sosa:Observation .
sosa:hasFeatureOfInterest ex:room100Foi .
sosa:resultTime "2021-01-01T08:00:00"^^xsd:dateTime ;
sosa:observedProperty "TEMP"^^xsd:string ;
sosa:hasSimpleResult "51.6"^^xsd:decimal .
ex:obs3Room100 a sosa:Observation .
sosa:hasFeatureOfInterest ex:room100Foi .
sosa:resultTime "2021-01-01T:16:00"^^xsd:dateTime ;
sosa:observedProperty "TEMP"^^xsd:string ;
sosa:hasSimpleResult "48.0"^^xsd:decimal .
# Room 1 sensor observations 1/2/2021
# ...
One attempt:
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix sosa: <http://www.w3.org/ns/sosa/>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
prefix ex: <http://www.example1.com/>
select ?oFoi ?day min(?val) as ?minTemp ?time where {
{select ?f where {
?f a sosa:FeatureOfInterest .
}}
?o a sosa:Observation ;
sosa:hasFeatureOfInterest ?oFoi ;
sosa:resultTime ?time ;
sosa:observedProperty ?p ;
sosa:hasSimpleResult ?val .
filter(?oFoi = ?f) .
bind(day(?t) as ?day) .
} group by ?oFoi ?day ?time
order by desc(?oFoi) asc(?day)
Result:
oFoi | day | minTemp | time |
---|---|---|---|
http://www.example.com/room1Foi | 1 | 51.4 | 2021-01-01 0:00:00 |
http://www.example.com/room1Foi | 1 | 50.2 | 2021-01-01 8:00:00 |
http://www.example.com/room1Foi | 1 | 49.8 | 2021-01-01 16:00:00 |
http://www.example.com/room1Foi | 2 | 59.8 | 2021-01-02 16:00:00 |
http://www.example.com/room1Foi | 2 | 60.2 | 2021-01-02 8:00:00 |
http://www.example.com/room1Foi | 2 | 61.4 | 2021-01-02 0:00:00 |
... | ... | ... | ... |
This doesn't work because ?time
must be included in the group by clause. Removing ?time
from group by clause will return the correct rows. However, ?time
is necessary to be included.
Ideal result:
oFoi | day | minTemp | time |
---|---|---|---|
http://www.example.com/room1Foi | 1 | 49.8 | 2021-01-01 16:00:00 |
http://www.example.com/room1Foi | 2 | 59.8 | 2021-01-02 16:00:00 |
... | ... | ... | ... |
Update: This gets closer but still is including multiple results when two times in the same day have the same temperature (both results included):
select ?o2 ?oFoi2 ?day2 ?val2 sample(?t2) as ?tx2 ?p2 where {
?o2 a sosa:Observation ;
sosa:hasFeatureOfInterest ?oFoi2 ;
sosa:resultTime ?t2 ;
sosa:observedProperty ?p2 ;
sosa:hasSimpleResult ?val2 .
bind(day(?t2) as ?day2) .
filter(?oFoi2 = ?oFoi) .
filter(?day2 = ?day) .
filter(?val2 = ?vx) .
{select ?oFoi ?day min(?val) as ?vx where {
{select ?f where {
?f a sosa:FeatureOfInterest .
}}
?o a sosa:Observation ;
sosa:hasFeatureOfInterest ?oFoi ;
sosa:resultTime ?t ;
sosa:observedProperty ?p ;
sosa:hasSimpleResult ?val .
filter(?oFoi = ?f) .
bind(day(?t) as ?day) .
} group by ?oFoi ?day
order by desc(?oFoi) asc(?day)
}
} group by ?o2 ?oFoi2 ?day2 ?p2 ?val2
Result:
o2 | oFoi2 | day2 | val2 | tx2 | p2 |
---|---|---|---|---|---|
http://www.example3.com/obs3Room100 | http://www.example3.com/room100Foi | 1 | 48 | 2021-01-01 16:00:00 |
"TEMP"^^http://www.w3.org/2001/XMLSchema#string |
http://www.example3.com/obs6Room1 | http://www.example3.com/room1Foi | 2 | 59.8 | 2021-01-02 16:00:00 |
"TEMP"^^http://www.w3.org/2001/XMLSchema#string |
http://www.example3.com/obs333Room1 | http://www.example3.com/room1Foi | 1 | -9.8 | 2021-01-01 16:00:00 |
"aTEMP"^^http://www.w3.org/2001/XMLSchema#string |
http://www.example3.com/obs33Room1 | http://www.example3.com/room1Foi | 1 | -9.8 | 2021-01-01 7:59:00 |
"aTEMP"^^http://www.w3.org/2001/XMLSchema#string |
... | ... | ... | ... | ... | ... |
Oops: ?o2
is unnecessary and removing it from the above query results in the correct solution.
Solution 1:[1]
Adding an outer select
appears to solve this. Using an aggregate for the time such as min()
, max()
, avg()
, sample()
, etc. are all valid approaches for aggregating the time variable. (Adding an extra property aTEMP
to help in understanding.)
Query:
select ?oFoi2 ?day2 ?val2 sample(?t2) as ?tx2 ?p2 where {
?o2 a sosa:Observation ;
sosa:hasFeatureOfInterest ?oFoi2 ;
sosa:resultTime ?t2 ;
sosa:observedProperty ?p2 ;
sosa:hasSimpleResult ?val2 .
bind(day(?t2) as ?day2) .
filter(?oFoi2 = ?oFoi) .
filter(?day2 = ?day) .
filter(?val2 = ?vx) .
{select ?oFoi ?day min(?val) as ?vx where {
{select ?f where {
?f a sosa:FeatureOfInterest .
}}
?o a sosa:Observation ;
sosa:hasFeatureOfInterest ?oFoi ;
sosa:resultTime ?t ;
sosa:observedProperty ?p ;
sosa:hasSimpleResult ?val .
filter(?oFoi = ?f) .
bind(day(?t) as ?day) .
} group by ?oFoi ?day
order by desc(?oFoi) asc(?day)
}
} group by ?oFoi2 ?day2 ?p2 ?val2
Result:
oFoi2 | day2 | val2 | tx2 | p2 |
---|---|---|---|---|
http://www.example3.com/room100Foi | 1 | 48 | 2021-01-01 16:00:00 |
"TEMP"^^http://www.w3.org/2001/XMLSchema#string |
http://www.example3.com/room1Foi | 2 | 59.8 | 2021-01-02 16:00:00 |
"TEMP"^^http://www.w3.org/2001/XMLSchema#string |
http://www.example3.com/room1Foi | 1 | -9.8 | 2021-01-01 7:59:00 |
"aTEMP"^^http://www.w3.org/2001/XMLSchema#string |
... | ... | ... | ... | ... |
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | There |