Bob MacGregor wrote:
Hi Lee,
Your example does the job. I have to congratulate you on your
proficiency. I do
have a couple of questions. One, the construct you are using is doing a max
computation. The (much simpler) construct I used did not (and there is
no max
in the conceptualization of the quuery). Also, when your
example executes, there will be a small cross product computed between the
different tags attached to each article. In my example, its a linear
scan. I'm
wondering if it the cross product is necessary in SPARQL, or if there is
another
way to capture this example that is more efficient and closer to the
true semantics
of the query.
Implementations are free to execute the query however they see fit, as
long as they produce the correct answer bindings. This could include
detecting constructs such as these and translating them to (e.g.)
min/max SQL calls.
I don't know a way to write the query in SPARQL w/o making use of the
cross-product approach.
Second, I'm wondering about the general case of universal
quantification. A
simple example would be something like "select people all of whose children
are male". I'm being lazy here, since I could search the sparql-dev
threads
looking for the solution. Do you have one at your fingertips that you
can point
me to? In our language, this would be
select ?person
from model
where (?person rdf:type Person) AND
UNSAID ((?person hasChild ?child) AND
UNSAID (?child gender "Male"))
it's the same style trick, just with a couple of subtleties.
PREFIX : <http://example.org/>
SELECT DISTINCT ?person
FROM <http://thefigtrees.net/lee/sw/data/gender.ttl>
WHERE {
?person a :Person .
OPTIONAL {
?person :child ?child .
?child :gender ?gender .
OPTIONAL {
?person :child ?otherchild .
?otherchild :gender ?othergender .
FILTER(?gender = "male" && ?otherchild != ?child) .
}
FILTER(!bound(?otherchild) || ?othergender = "male")
}
FILTER((!bound(?child) || ?gender = "male")
}
test data (at the URL above):
@prefix : <http://example.org/> .
:noChildrenOk a :Person .
:oneMaleChildOk a :Person ; :child [ :gender "male" ] .
:twoMaleChildrenOk a :Person ; :child [ :gender "male" ], [ :gender
"male" ] .
:oneFemaleChildNotOk a :Person ; :child [ :gender "female" ] .
:mixedChildrenNotOk a :Person ; :child [ :gender "male" ], [ :gender
"female" ] .
:twoFemaleChildrenNotOk a :Person ; :child [ :gender "female" ], [
:gender "female" ] .
results (again, you can test this at http://sparql.org)
?person:
<http://example.org/twoMaleChildrenOk>
<http://example.org/oneMaleChildOk>
<http://example.org/noChildrenOk>
Again, definitely not pretty or easy, but doable.
hope this helps,
Lee
Cheers, Bob
On Dec 10, 2007 11:24 PM, Lee Feigenbaum <[EMAIL PROTECTED]
<mailto:[EMAIL PROTECTED]>> wrote:
Bob MacGregor wrote:
> Hi Lee,
>
> OK, we'll try sparql dev, as long as this is a how to, rather than a
> "can't be
> done". But it looks to me like
> your query returns no bindings if an article does not have a
timetag. I
> say this because of the {?a ex:timetag ?maxtime} clause
> that comes before the OPTIONAL. But in that case, it should return
> the article. Can you fix this, or is it not expressible after all?
Right, I did that purposefully to concentrate on the "max" idiom. If you
want to include articles with no timetag, it becomes:
PREFIX : <http://example.org/>
SELECT ?a
FROM <http://thefigtrees.net/lee/sw/data/times.ttl
<http://thefigtrees.net/lee/sw/data/times.ttl>>
WHERE {
?a a :article .
OPTIONAL {
?a :timetag ?maxtime .
OPTIONAL {
?a :timetag ?othertime . FILTER(?othertime > ?maxtime)
}
FILTER (!bound(?othertime))
}
FILTER(!bound(?maxtime) || ?maxtime < 5)
}
The key is, I guess, to make the whole "find the max time" part optional
and then filter outside that on "there is no maxtime or the maxtime is
early enough".
(Note, I put some actual data at the above URL so that you can try this
out. To do this I changed the predicate names a bit and used integers
instead of datetimes for simplicity. I made "now" equal to 5. :-) ARQ
deployed at http://sparql.org is a great place to try it.)
The data is:
@prefix : <http://example.org/ > .
:onetimeOK a :article ; :timetag 1 .
:onetimeNotOK a :article ; :timetag 10 .
:twotimesOK a :article ; :timetag 1, 2 .
:twotimesNotOK a :article ; :timetag 1, 10 .
:notimeOK a :article .
... and when I run the above query through ARQ at sparql.org
<http://sparql.org> I get:
a:
<http://example.org/notimeOK <http://example.org/notimeOK>>
<http://example.org/twotimesOK>
<http://example.org/onetimeOK >
Lee
>
>
> In SPARQL, this query is (unedited, untested):
>
> SELECT ?a
> FROM :model
> WHERE {
> ?a rdf:type ft:article ; ex:timetag ?maxtime .
> OPTIONAL { ?a ex:timetag ?othertime . FILTER(?othertime >
?maxtime) }
> FILTER (!bound(?othertime) && ?maxtime > '...now...')
> }
>
> Original target:
>
>
> SELECT ?a
> FROM model
> WHERE
> (?a rdf:type ft:Article) AND
> UNSAID ((?a ex:timetag ?time) AND
> (?time > $NOW))
>
> =====================================
> Robert MacGregor
> Chief Scientist
> Siderean Software, Inc.
> [EMAIL PROTECTED] <mailto:[EMAIL PROTECTED]>
<mailto:[EMAIL PROTECTED] <mailto:[EMAIL PROTECTED]>>
> Mobile: 310-469-2810
> =====================================
--
=====================================
Robert MacGregor
Chief Scientist
Siderean Software, Inc.
[EMAIL PROTECTED] <mailto:[EMAIL PROTECTED]>
Mobile: 310-469-2810
=====================================