Reputation:
I have to database tables, where entities of the first Table may or may not have associated entries in the second table:
Table 1 Table 2
+-----+-----+ +-----+-------+-------+
| ID | ... | | ID | T1_ID | NAME |
+-----+-----+ +-----+-------+-------+
| 1 | ... | | 1 | 1 | p1 |
| 2 | ... | | 2 | 1 | p2 |
| 3 | ... | | 3 | 2 | p1 |
| 4 | ... | +-----+-------+-------+
+-----+-----+
I have the following queries i need to run:
Get all entities of Table_1 with a specific entry of Table_2 - That's easy, a simple Join will do...
Get all entities of Table_1, which don't have a specific entry of Table_2 associated - not so easy, but i also managed to query this with a join.
Get all entities of Table_1, which have a specific entry (A) and don't have another specific entry (B) associated, i.e. get all entities of Table_1 that have an entity of Table_2 with name=p1 and don't have an entity of Table_2 with name=p2 associated.
Is it possible to accomplish the kind of query from (3) in a single sql-statement without a sub-query?
Upvotes: 0
Views: 9590
Reputation: 8994
Get all entities of Table_1, which have a specific entry (A) and don't have another specific entry (B) associated, i.e. get all entities of Table_1 that have an entity of Table_2 with name=p1 and don't have an entity of Table_2 with name=p2 associated.
I'm having a bit of trouble understanding your criteria, but I think that is what you want:
SELECT *
FROM Table1 t1
JOIN Table2 t2 ON t1.ID = t2.t1_id
WHERE t2.name = 'p1'
AND NOT EXISTS(SELECT 'x' FROM Table2 t2_2 WHERE t1.ID = t2_2.t1_id AND t2_2.name = 'p2')
That will give you everything from Table1 that has a matching record in Table2 with name = 'p1' and DOESN'T have a matching record in Table2 with name = 'p2'. Is that what you need?
EDIT AGAIN:
I thought of a smarter way to do this that involves a static (non-correlated) subquery. This subquery will only be executed one time, rather than being executed once for every parent row in Table1. I didn't put this code through a query analyzer, but it should be significantly faster than of the queries using EXISTS(...)
SELECT *
FROM Table1 t1
JOIN Table2 t2 ON t1.ID = t2.t1_id
WHERE t2.name = 'p1'
AND t1.id NOT IN(SELECT t1_id FROM Table2 WHERE name = 'p2')
Upvotes: 4
Reputation: 77667
To make the variation of solutions more complete:
SELECT t1.*
FROM Table_1 t1
INNER JOIN Table_2 it2 ON t1.ID = it2.T1_ID AND it2.NAME = 'p1'
LEFT JOIN Table_2 lt2 ON t1.ID = lt2.T1_ID AND lt2.NAME = 'p2'
WHERE lt2.ID IS NULL
Upvotes: 0
Reputation: 21713
You can use an EXISTS
subquery (effectively the same as doing two joins).
SELECT * FROM Table_1 AS t1
WHERE EXISTS (SELECT * FROM Table_2 AS t2 WHERE t1.Id = t2.Id AND Name='p1')
AND NOT EXISTS (SELECT * FROM Table_2 AS t2 WHERE t1.Id = t2.Id AND Name='p2')
Upvotes: 3
Reputation: 76547
To get all occurrences where t2 matches t1.id but not some other field do
SELECT t1.id, t2.id FROM table2 t2
INNER JOIN table1 t1 ON (t2.t1_id = t1.id AND not(t2.fieldx <=> t1.fieldx))
Note that this will also exclude rows where both fieldx
are null
.
If you don't want that substitute the <=>
with =
.
Upvotes: 0