On 2017/03/22 4:14 PM, Hick Gunter wrote:
Since LEFT JOIN and RIGHT JOIN while also swapping the tables are
interchangeable, why should this not work?
SELECT ... FROM clients LEFT JOIN ON ... ( suppliers LEFT JOIN stock ON ...)
WHERE ...;
HI Gunter,
They are interchangeable for 1 vs. 1 join queries, but as soon as you
add a second lookup, they are not.
Your query won't work because this will not show ANY items that are NOT
explicitly part of the clients table. This is the problem with left-joins.
Your query will produce output like this (from my example below):
. ---- | ---- | ----
. A | NULL | NULL
. B | NULL | 1
. C | NULL | NULL
. D | $ | 2
. E | & | 4
You can see how that is different from what we needed in the original post.
To save time, I can distill the problem for you to the basics in a script:
------------------------------------------------------
-- SET-UP:
CREATE TABLE stock(id, cid, sid);
CREATE TABLE clients(id,name);
CREATE TABLE suppliers(id,name);
WITH CC(id) AS (SELECT 1 UNION ALL SELECT id+1 FROM CC WHERE id<7)
INSERT INTO stock(id) SELECT id FROM CC;
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;
-- Show content:
SELECT * FROM stock;
-- id | cid | sid
-- ------------ | ------ | ------
-- 1 | 1 | NULL
-- 2 | 2 | 1
-- 3 | 3 | 2
-- 4 | NULL | 3
-- 5 | NULL | 4
-- 6 | NULL | NULL
-- 7 | NULL | NULL
SELECT * FROM clients;
-- id | name
-- ------------ | -------
-- 1 | Hick1
-- 2 | Hick2
-- 3 | Hick3
SELECT * FROM suppliers;
-- id | name
-- ------------ | --------
-- 1 | Smith1
-- 2 | Smith2
-- 3 | Smith3
-- 4 | Smith4
-- One cumbersome solution to get the correct output:
SELECT clients.name, suppliers.name, stock.id
FROM clients
LEFT JOIN stock ON stock.cid=clients.id
LEFT JOIN suppliers ON stock.sid = suppliers.id
UNION
SELECT clients.name, suppliers.name, stock.id
FROM suppliers
LEFT JOIN stock ON stock.sid=suppliers.id
LEFT JOIN clients ON stock.cid = clients.id
ORDER BY 3
;
-- name | name | id
-- ------- | -------- | ------------
-- Hick1 | NULL | 1
-- Hick2 | Smith1 | 2
-- Hick3 | Smith2 | 3
-- NULL | Smith3 | 4
-- NULL | Smith4 | 5
-- Gunter's suggested query (I think, unless I got it wrong):
SELECT clients.name, A.name, stock.id
FROM clients
LEFT JOIN stock ON stock.cid = clients.id
LEFT JOIN (SELECT stock.id, name FROM suppliers LEFT JOIN stock ON
stock.sid = suppliers.id) AS A ON A.id = stock.id
ORDER BY 3
;
-- name | name | id
-- ------- | -------- | ------------
-- Hick1 | NULL | 1
-- Hick2 | Smith1 | 2
-- Hick3 | Smith2 | 3
-- Cleanup;
DROP TABLE suppliers;
DROP TABLE clients;
DROP TABLE stock;
As you can see, they are not the same - Smith3 & 4 never shows up in the
second query. If you can say how to get to the correct query using
simple joins (without the Union which is slow on large tables because of
duplication, and without CTEs), I'd be both impressed and thankful.
-----Ursprüngliche Nachricht-----
Von: sqlite-users [mailto:sqlite-users-boun...@mailinglists.sqlite.org] Im
Auftrag von R Smith
Gesendet: Mittwoch, 22. März 2017 14:30
An: sqlite-users@mailinglists.sqlite.org
Betreff: Re: [sqlite] RIGHT JOIN! still not supported?
On 2017/03/22 9:53 AM, Eric Grange wrote:
For the sake of curiosity, is anyone (as in any human) using RIGHT JOIN?
Personally I never had a need for a RIGHT JOIN, not because of
theoretical or design considerations, but it just never came into my
flow of thought when writing SQL...
I guess some automated SQL query generators could use it though,
because they do not have a "flow of thought".
I had a need of it the other day (something that can easily be overcome with a
CTE or subquery, but still may have made the sql read more natural):
We have one system which contains (among other things) clients, suppliers and
stock tables.
A stock item will mostly have a supplier and mostly will have an intended
client (the production is bespoke) except for a few common materials.
So we needed a list of all suppliers linked to all clients affected by them
(via Stock), and also see the clients who are not affected by any suppliers
(which should really be a minimum number) and the suppliers who are not
affecting any clients (which should also be a small list).
Note that not all suppliers may be linked to live stock items, and not all
clients may be linked to live stock items either - but they all need to show up
in the list.
If I can try my hand at a schematic of the sets showing links:
clients: [ A B C D E ]
- links | | |
stock: [ 1 2 3 4 5 ]
- links | | |
suppliers: [ @ # $ % & ! ]
I would need to see a "linking" query result showing overlap and non-links like
this:
. clnt | supp| stck
. ---- | ---- | ----
. A | NULL | NULL
. B | NULL| 1
. C | NULL| NULL
. D | $ | 2
. E | & | 4
. NULL | @ | NULL
. NULL | # | NULL
. NULL | % | 3
. NULL | ! | NULL
Note that I don't actually need the stck column, just adding it to show more
sensible results.
Also note that items linked to neither client nor supplier need not show up
(stock item 5 in this case), so I only need results having either a client or a
supplier.
The obvious solution was:
SELECT clients.name, suppliers.name
FROM clients
LEFT JOIN stock ON stock.client = clients.id
RIGHT JOIN suppliers ON stock.supplier = suppliers.id
WHERE (clients.name IS NOT NULL) OR (suppliers.name IS NOT NULL) ;
I suppose this could have worked too:
SELECT clients.name, suppliers.name
FROM suppliers
LEFT JOIN stock ON stock.supplier = suppliers.id
RIGHT JOIN clients ON stock.client = clients.id
WHERE (clients.name IS NOT NULL) OR (suppliers.name IS NOT NULL) ;
or even this:
SELECT clients.name, suppliers.name
FROM stock
RIGHT JOIN suppliers ON stock.supplier = suppliers.id
RIGHT JOIN clients ON stock.client = clients.id
WHERE (clients.name IS NOT NULL) OR (suppliers.name IS NOT NULL) ;
I don't see how to achieve that with simple joins in sqlite3. We used some CTEs
to LEFT JOIN stock to suppliers, and then left-joined that CTE on the stock to
the clients - which would also work using sub-query joins or filtered
cross-joins (much slower).
So to add to the discussion: Yeah, we've needed it, but overcoming the problem
was not exactly difficult and the use case itself is certainly not very common
(or even mildly common, it's rather uncommon).
Cheers,
Ryan
_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
___________________________________________
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
_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users