I have RDF data about hospital patients, including their date of birth. There are frequently multiple triples abut their date of birth, and some of those triples may be wrong. My group has decided to use this rule: whatever date occurs most frequently will provisionally be considered correct. It's clear how to do this in any programming language of our choice, external to SPARQL.
Is an aggregation of aggregations possible in SPARQL?
I have read the similar question SPARQL selecting MAX value of a counter, but I'm not there yet.
Given these triples:
@prefix turbo: <http://example.org/ontologies/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
<http://example.org/ontologies/b6be95364ec943af2ef4ab161c11c855>
a <http://example.org/ontologies/StudyPartWithBBDonation> ;
turbo:hasBirthDateO turbo:3950b2b6-f575-4074-b0e8-f9fa3378f3be, turbo:4250aafa-4b0c-4f73-92b6-7639f427b61d, turbo:a3e6676e-a214-4af4-b8ef-34a8e20170bf .
turbo:3950b2b6-f575-4074-b0e8-f9fa3378f3be turbo:hasDateValue "1971-12-30"^^xsd:date .
turbo:4250aafa-4b0c-4f73-92b6-7639f427b61d turbo:hasDateValue "1971-12-30"^^xsd:date .
turbo:a3e6676e-a214-4af4-b8ef-34a8e20170bf turbo:hasDateValue "1971-12-30"^^xsd:date .
turbo:6e200ca0d5150282787464a2bda55814
a turbo:StudyPartWithBBDonation ;
turbo:hasBirthDateO turbo:b09519f5-b123-40d5-bb4a-737ec9f8b9a8, turbo:06c56881-a6c7-4d1d-993b-add8862dffd7, turbo:12ef184d-c8d6-4d93-a558-a3ba47bb56ca .
turbo:b09519f5-b123-40d5-bb4a-737ec9f8b9a8 turbo:hasDateValue "2000-04-04"^^xsd:date .
turbo:06c56881-a6c7-4d1d-993b-add8862dffd7 turbo:hasDateValue "2000-04-04"^^xsd:date .
turbo:12ef184d-c8d6-4d93-a558-a3ba47bb56ca turbo:hasDateValue "2000-04-05"^^xsd:date .
This query
PREFIX turbo: <http://example.org/ontologies/>
SELECT ?part ?xsddate (COUNT(?xsddate) AS ?datecount)
{ ?part rdf:type turbo:StudyPartWithBBDonation ;
turbo:hasBirthDateO ?dob .
?dob turbo:hasDateValue ?xsddate
}
GROUP BY ?part ?xsddate
gives the following:
+----------------------------------------+------------------------+------------------+
| part | xsddate | datecount |
+----------------------------------------+------------------------+------------------+
| turbo:6e200ca0d5150282787464a2bda55814 | "2000-04-05"^^xsd:date | "1"^^xsd:integer |
| turbo:b6be95364ec943af2ef4ab161c11c855 | "1971-12-30"^^xsd:date | "3"^^xsd:integer |
| turbo:6e200ca0d5150282787464a2bda55814 | "2000-04-04"^^xsd:date | "2"^^xsd:integer |
+----------------------------------------+------------------------+------------------+
I only want to see the date with the highest count for each patient who is participating in a study:
+----------------------------------------+------------------------+------------------+
| part | xsddate | datecount |
+----------------------------------------+------------------------+------------------+
| turbo:b6be95364ec943af2ef4ab161c11c855 | "1971-12-30"^^xsd:date | "3"^^xsd:integer |
| turbo:6e200ca0d5150282787464a2bda55814 | "2000-04-04"^^xsd:date | "2"^^xsd:integer |
+----------------------------------------+------------------------+------------------+
I think I'm getting close here. Now I need to get the counts and max counts on the same row!
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX turbo: <http://example.org/ontologies/>
SELECT ?part ?xsddate ?datecount ?countmax
WHERE
{ { SELECT ?part ?xsddate (COUNT(?xsddate) AS ?datecount)
WHERE
{ ?part rdf:type turbo:StudyPartWithBBDonation ;
turbo:hasBirthDateO ?dob .
?dob turbo:hasDateValue ?xsddate
}
GROUP BY ?part ?xsddate
}
UNION
{ SELECT ?part (MAX(?datecount) AS ?countmax)
WHERE
{ SELECT ?part ?xsddate (COUNT(?xsddate) AS ?datecount)
WHERE
{ ?part rdf:type turbo:StudyPartWithBBDonation ;
turbo:hasBirthDateO ?dob .
?dob turbo:hasDateValue ?xsddate
}
GROUP BY ?part ?xsddate
}
GROUP BY ?part
}
}
giving
+----------------------------------------+------------------------+------------------+------------------+
| part | xsddate | datecount | countmax |
+----------------------------------------+------------------------+------------------+------------------+
| turbo:6e200ca0d5150282787464a2bda55814 | "2000-04-05"^^xsd:date | "1"^^xsd:integer | |
| turbo:b6be95364ec943af2ef4ab161c11c855 | "1971-12-30"^^xsd:date | "3"^^xsd:integer | |
| turbo:6e200ca0d5150282787464a2bda55814 | "2000-04-04"^^xsd:date | "2"^^xsd:integer | |
| turbo:6e200ca0d5150282787464a2bda55814 | | | "2"^^xsd:integer |
| turbo:b6be95364ec943af2ef4ab161c11c855 | | | "3"^^xsd:integer |
+----------------------------------------+------------------------+------------------+------------------+