After some thinking I came up with this:

First, set up the example (note: no CTE as I am still runnning SQLIte 3.7.14.1):

CREATE temp TABLE stock(id, cid, sid);
CREATE temp TABLE clients(id,name);
CREATE temp TABLE suppliers(id,name);
insert into stock (id) values (1),(2),(3),(4),(5),(6),(7);
UPDATE stock SET cid = id WHERE id < 4;
UPDATE stock SET sid = id - 1 WHERE id BETWEEN 2 AND 5;
INSERT INTO clients   SELECT cid, 'Hick'||cid   FROM stock WHERE cid IS NOT 
NULL;
INSERT INTO suppliers SELECT sid, 'Smith'||sid FROM stock WHERE sid IS NOT NULL;


The desired output contains rows that have a NULL client, so may as well create 
a view for this (NOTE: renaming the columns to indicate the table they are 
from):

create temp view clients_null as select id as cid,name as cname from clients 
union all select null, null;


The same holds for rows that have a NULL supplier, so create a view for this 
too (NOTE: renaming as above):

create temp view suppliers_null as select id as sid,name as sname from 
suppliers union all select null, null;


Now we are ready to produce all possible rows, may as well do this with a view 
too:

create temp view all_rows as select * from clients_null, suppliers_null;


And for the grand finale, join with stock to retrieve
    1) stock connecting client to supplier
    2) client with stock not connected to supplier
    3) supplier with stock not connected to client
(NOTE: not a single LEFT or RIGHT join required)
(NOTE: if we could indicate that NULL == NULL should be true, just the first 
expressions should suffice):

select cname,sname,id from all_rows a join stock s on ((a.sid = s.sid) and 
(a.cid = s.cid)) or ((a.cid = s.cid) and (a.sid is null) and (s.sid is NULL)) 
or ((a.sid = s.sid) and (a.cid is null) and (s.cid is NULL));

cname|sname|id
Hick1|NULL|1
Hick2|Smith1|2
Hick3|Smith2|3
NULL|Smith3|4
NULL|Smith4|5


Adding a dummy value instead of NULL yields (NOTE: where clause to eliminate 
totally unconnected stock items):

select cname,sname,id from all_rows a join stock s on (ifnull(a.sid,-1) = 
ifnull(s.sid,-1)) and (ifnull(a.cid,-1) = ifnull(s.cid,-1)) where cname not 
null or sname not null;


Pursuing this idea further leads to:

drop view clients_null;
drop view suppliers_null;
create temp view clients_null as select id as cid,name as cname from clients 
union all select -1, null;
create temp view suppliers_null as select id as sid,name as sname from 
suppliers union all select -1, null;
create temp view stock_dummy as select id,ifnull(sid,-1) as sid,ifnull(cid,-1) 
as cid from stock;

and the quite readable statement:

select cname,sname,id from all_rows a join stock_dummy s on (a.sid = s.sid) and 
(a.cid = s.cid) where cname not null or sname not null;



___________________________________________
 Gunter Hick
Software Engineer
Scientific Games International GmbH
FN 157284 a, HG Wien
Klitschgasse 2-4, A-1130 Vienna, Austria
Tel: +43 1 80100 0
E-Mail: h...@scigames.at

This communication (including any attachments) is intended for the use of the 
intended recipient(s) only and may contain information that is confidential, 
privileged or legally protected. Any unauthorized use or dissemination of this 
communication is strictly prohibited. If you have received this communication 
in error, please immediately notify the sender by return e-mail message and 
delete all copies of the original communication. Thank you for your cooperation.


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

Reply via email to