- From: Eric Prud'hommeaux <eric@w3.org>
- Date: Mon, 28 Nov 2011 15:35:40 -0500
- To: David McNeil <dmcneil@revelytix.com>
- Cc: public-rdf-dawg-comments@w3.org
* David McNeil <dmcneil@revelytix.com> [2011-11-28 11:20-0600] > Eric - Thanks for the responses, that is helpful. I have another comment > below. > > On Mon, Nov 28, 2011 at 11:10 AM, Eric Prud'hommeaux <eric@w3.org> wrote: > > > > 4) Given that definition, can't the Filter be pushed down below the > > > LeftJoin? In this way LeftJoin could be simplified because it would no > > > longer need to take an expression. > > > > If I understand, that would remove compatible rows with failed > > filters, as opposed to retaining the row on the left side of the > > optional. > > > > The way I am thinking of it since it is a LeftJoin, the compatible rows > with failed filters would be removed from the right side, but since it is a > LeftJoin, the rows on the left would be retained (since that is what a > LeftJoin does). yep, but the wierd bit is that the filter in the OPTIONAL is scoped to both the left and right sides of the OPTIONAL: [[ SELECT ?label { { {SELECT*{BIND(1 AS?match) BIND(10 AS?x)}} } OPTIONAL { {SELECT*{BIND("COMPAT PASS" AS?label) BIND(1 AS?match)BIND(10 AS?y)}} UNION {SELECT*{BIND("COMPAT FAIL" AS?label) BIND(1 AS?match)BIND(11 AS?y)}} UNION {SELECT*{BIND("INCOMPAT" AS?label) BIND(2 AS?match)BIND(10 AS?y)}} FILTER (?x = ?y) } } ]] --stem http://ucsc.example/uniProt/ -S mysql://genome@genome-mysql.cse.ucsc.edu/uniProt -e 'PREFIX Ugene: <http://ucsc.example/uniProt/gene#> SELECT ?gene_symbol WHERE { _:gene <http://ucsc.example/uniProt/gene#acc> "P04637" . _:gene <http://ucsc.example/uniProt/gene#val> ?gene_symbol . }' In SQL-land, this would require duplicating the left-hand side of the query. In triples: [[ CREATE TABLE __HOLDS__ (s VARCHAR(40), p VARCHAR(40), o VARCHAR(40)); INSERT INTO __HOLDS__ (s, p, o) VALUES ("<s1>", "<match>", "1"), ("<s1>", "<x>", "10"); INSERT INTO __HOLDS__ (s, p, o) VALUES ("<s2a>", "<label>", "\"COMPAT PASS\""), ("<s2a>", "<match>", "1"), ("<s2a>", "<y>", "10"); INSERT INTO __HOLDS__ (s, p, o) VALUES ("<s2b>", "<label>", "\"COMPAT FAIL\""), ("<s2b>", "<match>", "1"), ("<s2b>", "<y>", "11"); INSERT INTO __HOLDS__ (s, p, o) VALUES ("<s2c>", "<label>", "\"INCOMPAT\"" ), ("<s2c>", "<match>", "2"), ("<s2c>", "<y>", "10"); CREATE VIEW l AS SELECT a.o AS "?match", b.o AS "?x" FROM __HOLDS__ AS a INNER JOIN __HOLDS__ AS b ON b.s=a.s WHERE a.s="<s1>" AND a.p="<match>" AND b.p="<x>"; +--------+------+ | ?match | ?x | +--------+------+ | 1 | 10 | +--------+------+ ]] I can't create a view which carries that x=y constraint because there is no x in that scope. I can keep it, however, if I promise to restrict it later: [[ CREATE VIEW r AS SELECT a.o AS "?label", b.o AS "?match", c.o AS "?y" FROM __HOLDS__ AS a INNER JOIN __HOLDS__ AS b ON b.s=a.s INNER JOIN __HOLDS__ AS c ON c.s=a.s WHERE a.p="<label>" AND b.p="<match>" AND c.p="<y>"; +---------------+--------+------+ | ?label | ?match | ?y | +---------------+--------+------+ | "COMPAT PASS" | 1 | 10 | | "COMPAT FAIL" | 1 | 11 | | "INCOMPAT" | 2 | 10 | +---------------+--------+------+ ]] We can outer join them now, but we've forgotten about our constraint: [[ SELECT * FROM l LEFT OUTER JOIN r ON l.`?match` = r.`?match`; +--------+------+---------------+--------+------+ | ?match | ?x | ?label | ?match | ?y | +--------+------+---------------+--------+------+ | 1 | 10 | "COMPAT PASS" | 1 | 10 | | 1 | 10 | "COMPAT FAIL" | 1 | 11 | +--------+------+---------------+--------+------+ ]] [[ CREATE VIEW t AS SELECT l.`?match`, l.`?x`, r.`?label`, r.`?y` FROM l INNER JOIN r ON l.`?match` = r.`?match` WHERE l.`?x`=r.`?y`; +--------+------+---------------+------+ | ?match | ?x | ?label | ?y | +--------+------+---------------+------+ | 1 | 10 | "COMPAT PASS" | 10 | +--------+------+---------------+------+ ]] We can then outer join l against t (which already has l in it): [[ SELECT * FROM l LEFT OUTER JOIN t ON l.`?match` = t.`?match`; +--------+------+--------+------+---------------+------+ | ?match | ?x | ?match | ?x | ?label | ?y | +--------+------+--------+------+---------------+------+ | 1 | 10 | 1 | 10 | "COMPAT PASS" | 10 | +--------+------+--------+------+---------------+------+ ]] This looks identical to if we'd [[ SELECT * FROM l LEFT OUTER JOIN r ON l.`?match` = r.`?match` WHERE l.`?x` = r.`?y`; +--------+------+---------------+--------+------+ | ?match | ?x | ?label | ?match | ?y | +--------+------+---------------+--------+------+ | 1 | 10 | "COMPAT PASS" | 1 | 10 | +--------+------+---------------+--------+------+ ]] , but recall that if l had an incompatible row, say either of the last two of +--------+------+ | ?match | ?x | +--------+------+ | 1 | 10 | | 1 | 12 | | 3 | 10 | +--------+------+ , we'd expect to see them in the left left join. btw, will you be coming to http://www.w3.org/2011/09/LinkedData/ ? (want to register?) > -David -- -ericP
Received on Monday, 28 November 2011 20:36:19 UTC