I'm new to sparql and trying to fegure out what is the best way to select the max value of a counter of another query without creating a new table, only using sub-queries. I'm working on a relatively small dataset so the computation time is not a problem.
SELECT ?p1 ?c1 (MAX(?cnt1) AS ?maxc)
WHERE{
{
SELECT ?p1 ?c1 (COUNT(?s1) AS ?cnt1)
WHERE {
?s1 ?p1 ?o1;
a ?c1.
}Group by ?p1 ?c1
#ORDER BY ?p1 DESC(?cnt1)
}
}GROUP BY ?p1
so I'm expecting to get a row for every value of ?p1 with the max ?cnt1 the suitable ?c1
I'm pretty sure that is the way to do that but for some reason it causes my endpoint to crash. the inner query works fine and when grouping by both ?p1 and
?c1 it produces just one line and the max value is empty.
Thanks,
Omri
Your query will crash unless you are grouping by both ?p1 and ?c1.
When grouping, all variables appearing in SELECT must ether appear in the GROUP or in an aggregation function (MAX, COUNT, etc.).
The following query will give you the maximum value of your counter, but without the corresponding ?p1 ?c1. To have those, you will likely need another sub-query with a FILTER in it...
SELECT (MAX(?cnt1) AS ?maxc)
WHERE{
{
SELECT ?p1 ?c1 (COUNT(?s1) AS ?cnt1)
WHERE {
?s1 ?p1 ?o1;
a ?c1.
}Group by ?p1 ?c1
}
}
Related
I have an ontology Model. I am inserting integer data in one of the class instance through Sparql update. The model is storing the data randomly with out any order. Now when I want to extract this data through Sparql Query I want it in order of the time of insertion. How could i achieve this? Any idea?
P.S: My ontology Model is made in Protege software.
My Query for inserting Data is below one.
PREFIX test:<http://www.semanticweb.org/muhammad/ontologies/2017/2/untitled-ontology-14#>
INSERT {
?KPI_Variables test:hasValue_ROB1 10
} WHERE {
?KPI_Variables test:hasValue_ROB1 ?Newvalue
FILTER(?KPI_Variables= test:Actual_Production_Time)
}
And For Getting the data I am using the following Query:
PREFIX test:<http://www.semanticweb.org/muhammad/ontologies/2017/2/untitled-ontology-14#>
SELECT ?KPI_Variables ?Newvalue WHERE {
?KPI_Variables test:hasValue_ROB1 ?Newvalue
FILTER(?KPI_Variables = test:Actual_Production_Time)
} LIMIT 25
Data in RDF is simply triples. There's no notion of when a triple is added to a graph. If you want that kind of information, you'll need to make it explicit in your data model. SPARQL does include a now function that lets you get a timestamp for when a query is run. That means that you could do something like this:
prefix : <urn:ex:>
insert {
[] :hasSubject ?s ;
:hasPredicate ?p ;
:hasObject ?o ;
:hasTime ?now .
}
where {
#-- Fake a couple of triples
values (?s ?p ?o) {
(:a :p :b)
(:c :q :d)
}
#-- Get the current time
bind (now() as ?now)
}
Now your graph contains data like:
#prefix : <urn:ex:> .
[ :hasObject :d ;
:hasPredicate :q ;
:hasSubject :c ;
:hasTime "2017-04-28T13:32:11.482+00:00"^^<http://www.w3.org/2001/XMLSchema#dateTime>
] .
[ :hasObject :b ;
:hasPredicate :p ;
:hasSubject :a ;
:hasTime "2017-04-28T13:32:11.482+00:00"^^<http://www.w3.org/2001/XMLSchema#dateTime>
] .
Which you can query like:
prefix : <urn:ex:>
select ?s ?p ?o ?time {
[] :hasSubject ?s ;
:hasPredicate ?p ;
:hasObject ?o ;
:hasTime ?time
}
order by ?time
s,p,o,time
urn:ex:c,urn:ex:q,urn:ex:d,2017-04-28T13:32:11.482+00:00
urn:ex:a,urn:ex:p,urn:ex:b,2017-04-28T13:32:11.482+00:00
Once you've inserted some things at different times, you'd have different time values, so sorting would be meaningful. I'd suggest that you don't just reify the triples like I did (and if you are going to go with a straightfoward reification, you should probably use the standard vocabulary for it), but rather have some meaningful structure that actually has timestamps as part of it.
I would like to add a computed field in my select result using Eloquent.
$dbEntry->query->select('id', '(s1 + s2) as scoreSum')->toSql();
// "select `id`, `(s1` as `s2)` from `mytable`"
I would expect:
// "select `id`, `s1` + `s2` as scoreSum from `mytable`"
Context: in my real world stuff, what I am computing is an haversine formula (on a limited set of entries).
You need to use a raw query instead, e.g. like this:
->select(DB::raw('id, (s1 + s2) as scoreSum'))
Make sure you import the DB as well.
I am trying to understand how to do filtering in SPARQL with combined AND and OR conditions.
I try to find all physicists living within Newton's lifetime via the Wikidata Query Service (query.wikidata.org). This is my query:
SELECT ?p1 ?p1Label ?p1t1 ?p1t2 ?p2 ?p2Label ?p2t1 ?p2t2
WHERE {
FILTER (?p1=wd:Q935) . # Newton
?p1 wdt:P569 ?p1t1 . # date of birth
?p1 wdt:P570 ?p1t2 . # date of death
?p2 wdt:P106 wd:Q169470 . # physicist
?p2 wdt:P569 ?p2t1 . # date of birth
?p2 wdt:P570 ?p2t2 . # date of death
{ FILTER (xsd:dateTime(?p2t1) > xsd:dateTime(?p1t1))
. FILTER (xsd:dateTime(?p2t1) < xsd:dateTime(?p1t2)) }
UNION
{ FILTER (xsd:dateTime(?p2t2) > xsd:dateTime(?p1t1))
. FILTER (xsd:dateTime(?p2t2) < xsd:dateTime(?p1t2)) }
UNION
{ FILTER (xsd:dateTime(?p2t1) < xsd:dateTime(?p1t1))
. FILTER (xsd:dateTime(?p2t2) > xsd:dateTime(?p1t2)) } .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
}
ORDER BY xsd:dateTime(?p2t1)
The query can be processed but does not yield any results.
Each one of the three { FILTER . FILTER } blocks works fine when used without the others.
What am I doing wrong?
{ FILTER (xsd:dateTime(?p2t1) > xsd:dateTime(?p1t1))
. FILTER (xsd:dateTime(?p2t1) < xsd:dateTime(?p1t2)) }
evaluates to empty.
UNION does not "or" them together -- || does that.
Each branch of the UNION is a separate graph pattern.
I have a query delete/insert that I'd like to optimize if possible. The query does delete/insert on up to 50 objects at a time. My Jmeter tests show that the DELETE clause takes 4 times longer in comparison to INSERT: delete takes around 3300 ms and insert takes about 860 ms. I'd like to improve the DELETE clause. I was thinking of using FILTER, but was told it would not scale well. Any recommendation is much appreciated.
What I have right now is:
DELETE {
?s ?p ?o.
?collection dc:identifier ?cid;
rdf:type ?ct;
rdf:li ?list.
?list rdf:first ?first;
rdf:rest ?rest.
}
WHERE
{
{ ?s dc:identifier "11111"^^xsd:int; ?p ?o. }
UNION { ?s dc:identifier "22222"^^xsd:int; ?p ?o.}
UNION {?s dc:identifier "33333"^^xsd:int; ?p ?o.}
UNION{} UNION{}.......
OPTIONAL{
?s dc:hasPart ?collection.
?collection dc:identifier ?cid;
rdf:type ?ct;
rdf:li ?list.
?list rdf:first ?first;
rdf:rest ?rest.
}
INSERT DATA
{
GRAPH <http://test.org/>
{.....}
GRAPH <http://test.org/>
{.....}
GRAPH....
}
Without having your data, or even knowing what triple store you're using, we can't really help much in optimization. It might just be that deletes are more expensive than insertions. That said, one thing that might help is to use values rather than unions in your where block. That is, instead of:
{ ?s dc:identifier "11111"^^xsd:int; ?p ?o. }
UNION { ?s dc:identifier "22222"^^xsd:int; ?p ?o.}
UNION {?s dc:identifier "33333"^^xsd:int; ?p ?o.}
UNION{} UNION{}.......
do:
values ?identifier { "11111"^^xsd:int "22222"^^xsd:int "33333"^^xsd:int "44444"^^xsd:int }
?s dc:identifier ?identifier ; ?p ? o
I just started using SPARQL, and I'm trying to create a query that retrieves all information where an id has one of a number of predefined values? I have something like this :
SELECT *
WHERE {
?id ?property ?value .
?value a ?type .
?type rdfs:label ?type_value .
FILTER ( ?id IN (<id1>,<idi>,<idn> ) )
}
The problem I've been running into is the query gets really slow when the list of ids gets increasingly large. I intuitively think there's a better way to write this query, but I'm having trouble figuring out how to create this kind of query. I'm thinking along the lines of something like this:
SELECT *
WHERE {
<id_value> ?property ?value .
?value a ?type .
?type rdfs:label ?type_value .
}
where it retrieves all values only for the multiple ids, eliminating the filtering of results at the end, but I can't figure out how to write the query so that it returns all values for an id_value. when I add another line for another id_value, it filters out other values I'm expecting, so I think I'm writing it incorrectly. How can I do this?
Using values, you can write:
SELECT * WHERE {
values ?id { <id1> <idi> <idn> }
?id ?property ?value .
?value a ?type .
?type rdfs:label ?type_value .
}
The SPARQL 1.1 says about values:
Data can be directly written in a graph pattern or added to a query
using VALUES. VALUES provides inline data as a solution sequence which
are combined with the results of query evaluation by a join operation.
It can be used by an application to provide specific requirements on
query results and also by SPARQL query engine implementations that
provide federated query through the SERVICE keyword to send a more
constrained query to a remote query service.
One of the examples is actually very close to what you've already got:
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX : <http://example.org/book/>
PREFIX ns: <http://example.org/ns#>
SELECT ?book ?title ?price
{
VALUES ?book { :book1 :book3 }
?book dc:title ?title ;
ns:price ?price .
}
Try using the VALUES clause instead like so:
SELECT *
WHERE {
VALUES ?id { ...list of ids... }
?id ?property ?value .
?value a ?type .
?type rdfs:label ?type_value .
}
This should hopefully be much more efficient that using the FILTER approach.