Guys,

Just a clarification to my previous post: I'm not looking for a solution to my 
example problem (but thanx anyway for the suggestions).
What I'm really trying to understand is if the behaviour of the LEFT JOIN 
operator is correct.
I think SQlLite produces the wrong result, but please correct me if I'm wrong.

My statement:

SELECT * FROM C
    LEFT JOIN A ON A.a*A.a + B.b*B.b = C.c*c.c
    LEFT JOIN B ON A.a*A.a + B.b*B.b = C.c*c.c;
 
Should be interpreted as

SELECT * FROM (C LEFT JOIN
               A ON A.a*A.a + B.b*B.b = C.c*c.c)
     LEFT JOIN B ON A.a*A.a + B.b*B.b = C.c*c.c;

The "C LEFT JOIN A" part is to be evaluated first; produces output for all 
value in C (only value 5). Each of these rows of C is completed either with all 
suitable value of A, or NULL if such value does not exist.
Sqlite should find 2 candidates from A (values 3 and 4).  The a values 1, 2, 
and 5 are not suitable, since they can never satisfy the ON clause. (Note that 
for finding these suitable values in A  SqLite also needs to look into table B, 
but that is, I think, an implementtion detail)


 So the result of "C LEFT JOIN A" is
   c a
   - -
   5 3
   5 4

This intermediate table is LEFT JOINed with B. Again, this means that if a 
suitable b can be found it will complete the row with this b, and otherwise 
with NULL.
Since both rows can be completed with suitable values of B the end result would 
be:

   c a b
   - - -
   5 3 4
   5 4 3


But SqLite produces additional 3 rows
  c a b
  - - -
  5 1 <null>           -- additional row
  5 2 <null>           -- additional row
  5 3
  5 4
  5 5 <null>           -- additional row

It looks like SqLite interprets the query as
(warning pseudo sql)

SELECT * FROM C
      LEFT JOIN (          A ON A.a*A.a + B.b*B.b = C.c*c.c
                 LEFT JOIN B ON A.a*A.a + B.b*B.b = C.c*c.c);

So for each value in A it tries to find a suitable value in B resulting in
  a b
  - -
  1 <null>
  2 <null>
  3 4
  4 3
  5 <null>

and then JOINs C with this intermediate table.
leading to:
 c a b
 - - -
 5 1 <null>
 5 2 <null>
 5 3 4
 5 4 3
 5 5 <null>

So my question if Sqlite produces the correct result remains. I think it 
doesn't.

 
 
Regards,

Rob

 
 
The join is valid and the results are perfectly ok.

You are using LEFT JOIN, which produces a row even if there is NO MATCH on the 
RHS, returning NULL for fields selected from there.


SELECT * FROM C JOIN A ON A.a*A.a + B.b*B.b = C.c*c.c JOIN B ON A.a*A.a + 
B.b*B.b = C.c*c.c;

c           a           b
----------  ----------  ----------
5           3           4
5           4           3



-----Urspr?ngliche Nachricht-----
Von: Rob Golsteijn [mailto:rob.golste...@mapscape.eu]
Gesendet: Donnerstag, 16. J?nner 2014 11:21
An: sqlite-users@sqlite.org
Betreff: [sqlite] Mutally dependent JOIN clauses

Dear List,

I came across a query with 2 LEFT JOINs of which the join clauses were mutually 
dependent.
They did not produce the result I expected, but now I wonder if this is legal 
SQL in the first place.
I created a small example which illustrates the problem.
The example tries to find Pythagorean Triples (i.e. integers a, b, and c for 
which holds a^2 + b^2 = c^2) for given set of possible values for a, b, and c.
Note: that in my query the JOIN-clause of A refers to table B that is LEFT 
JOINed later, and the JOIN clause of B refers back to table A.


.headers on

.null <null>
CREATE TABLE A (a INTEGER);
CREATE TABLE B (b INTEGER);
CREATE TABLE C (c INTEGER);

INSERT INTO C VALUES(5);

INSERT INTO A VALUES(1);
INSERT INTO A VALUES(2);
INSERT INTO A VALUES(3);
INSERT INTO A VALUES(4);
INSERT INTO A VALUES(5);

INSERT INTO B VALUES(1);
INSERT INTO B VALUES(2);
INSERT INTO B VALUES(3);
INSERT INTO B VALUES(4);
INSERT INTO B VALUES(5);

SELECT * FROM C
    LEFT JOIN A ON A.a*A.a + B.b*B.b = C.c*c.c
    LEFT JOIN B ON A.a*A.a + B.b*B.b = C.c*c.c;
c|a|b
5|1|<null>
5|2|<null>
5|3|4
5|4|3
5|5|<null>

When I look at the first result row and substitute that in the JOIN clause of A 
I get
     1*1 + NULL*NULL= 5*5
which is definitely not true since the lhs of the expression is NULL and the 
rhs 25.
This made me wonder which value Sqlite uses for B.b when it is LEFT JOINing 
table A.
It is appearantly not the value that is actually used when LEFT JOINing table B.

I don't know exactly what to expect from Sqlite. Either
(1) an error indicating that it is illegal to refer in the JOIN clause of a 
LEFT JOIN to a table that is LEFT JOINed later; or
(2) only the result rows
       c|a|b
       5|3|4
       5|4|3
but neither of these options is the case. Is this valid SQL that Sqlite cannot 
handle or is this just invalid SQL?
In the latter case it would be nice if SqLite complained about it).



Rob Golsteijn

 
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to