UNSAID - two test cases

Two test cases: data, queries, results and manifest.ttl attached.

The first is based on the dawg-comments message, with multiple triples with 
the same property; the second is Steve's "exactly one email address" done 
with UNSAID and also with OPTIONAL.

 Andy


==== Case 1: selecting a resource based on the absence of a type triple:

An example like this has just been asked on jena-dev.

"Find all the things that are not of a given class."

Suppose the data is:

   <x> rdf:type :foo .
   <x> rdf:type :bar .

then it needs something like:

     UNSAID(?thing rdf:type :foo)

Doing this without UNSAID might take two queries and the application needs
to calculate the set difference (find all ?x (Q1), find all ?x which have
type :foo (Q2) and take all ?x in Q2 out of Q1).

Turning into a test case:

== Data 1:
@prefix : <http://example.org/ns#> .

:x a :foo .
:x a :bar .

:y a :bar .

== Query 1:
PREFIX : <http://example.org/ns#>

SELECT ?r
WHERE (?r rdf:type ?type)        # Get all the things with a type
       UNSAID (?r rdf:type :foo)

== Result Set 1:
------
| r  |
======
| :y |
------

==== Case 2:

This is a great test case from Steve:
"find all the people with exactly one known email address"

might be:

SELECT ?person
WHERE
   (?person :email ?e1)
   UNSAID { (?person :email ?e2) AND ?e2 NE ?e1 }

but also optionals+constraints can do it:

PREFIX : <http://example.org/ns#>

SELECT ?person
WHERE  (?person :email ?e1)
    OPTIONAL { (?person :email ?e2) AND ?e2 NE ?e1 }
    AND ! &dawg:bound(?e2)

using the same method Steve had of using optional, then inverting the sense
of the match with dawg:bound.


== Data 2:
@prefix : <http://example.org/ns#> .

:p1 :email <mailto:p1e1> .
:p1 :email <mailto:p1e2> .

:p2 :email <mailto:me> .

== Query 2.1:
PREFIX : <http://example.org/ns#>

SELECT ?person
WHERE  (?person :email ?e1)
        UNSAID { (?person :email ?e2) AND ?e2 NE ?e1 }

== Result Set 2.1
----------
| person |
==========
| :p2    |
----------

((
I was surprised that this worked at all.  On reflection, I can see it done
with something like a subquery in SQL and using NOT IN

See MySQL manual "13.1.8.3 Subqueries with ANY, IN, and SOME"
http://dev.mysql.com/doc/mysql/en/Subqueries.html
))


== Query 2.2:
I haven't implemented functions yet so I had to try this and eyeball the
results:

PREFIX : <http://example.org/ns#>
SELECT ?person ?e1 ?e2
WHERE  (?person :email ?e1)
        OPTIONAL { (?person :email ?e2) AND ?e2 NE ?e1 }

== Result Set 2.2
------------------------------------------
| person | e1            | e2            |
==========================================
| :p1    | <mailto:p1e2> | <mailto:p1e1> |
| :p1    | <mailto:p1e1> | <mailto:p1e2> |
| :p2    | <mailto:me>   |               |
------------------------------------------

so testing for ?e2 unbound would get just :p2

Note the excessive hits on :p1 as there is combinatorial growth by asking
for :email twice.  Adding a third email for :p1 gets 6 rows etc etc.
It could be argued that this is where the cost of a subquery has gone.

 Andy

Received on Wednesday, 22 December 2004 10:26:46 UTC