Query a table using conditions with another table - sql

Hard to make a good title for this (feel free to edit), but hope it will make more sense ..
Say I have the following tables:
t1:
i1 v1
_________
1 bob
2 NULL
3 sam
4 NULL
5 kenny
5 NULL
t2:
i2 v2 item
______________
1 bob prod_1
2 nick prod_2
3 sam prod_3
4 jj prod_4
5 kenny prod_5
5 cartman prod_6
I need to JOIN the tables on t2.i2 = t1.i1 but only where t2.v2 does not exist in t1.v1. So I'm trying to get the following results:
Goal:
i2 v2 item
__________________
2 nick prod_2
4 jj prod_4
5 cartman prod_6
This query below was my first attempt, and it's not working, so I'm trying to find a working and more efficient solution with JOINs.
SELECT * FROM t2
WHERE v2 NOT IN (
SELECT v1 FROM t1 WHERE t2.i2 = t1.i1
)

Your query is fine, although I would use NOT EXISTS:
SELECT dm2.*
FROM web.delete_me2 dm2
WHERE NOT EXISTS (SELECT 1
FROM web.delete_me1 dm1
WHERE dm2.some_int2 = dm1.some_int1 and dm2.some_var2 = dm1.some_var1
);
Although you can write this as a join, this version should be at least as good performance wise. You want an index on web.delete_me1(some_int1, some_var1).

A LEFT JOIN should be enough
select * From t2
left join t1 on t2.i2 = t1.i1 and t1.v1= t2.v2
where t1.i1 is null

SELECT DISTINCT T1.*, T2.*
FROM T1
JOIN T2
ON T1.ID = T2.ID
LEFT JOIN T2 AS T2NO
ON T2NO.NAME = T1.NAME
WHERE T2NO.NAME IS NULL
or try this
SELECT DISTINCT T2.*
FROM T2
JOIN T1
ON T1.ID = T2.ID
LEFT JOIN T1 AS T1NO
ON T1NO.NAME = T2.NAME
WHERE T1NO.NAME IS NULL

Do you need all records from t2 where i2 is in t1 and v2 is not?
If so, you can write this query
select * from t2
where i2 in (select i1 from t1)
and v2 not in (select v1 from t1 where v1 is not null)
for not in to work as we need, v1 shouldn't be null

Related

SQL three tables using only JOIN

I have three tables: T1 has id's from T2 (client) and T3 (supplier), it also acts a black list: T1's rows with client's and supplier's id.
I want to get the supplier's id the client can buy from.
.
currently T1 has three rows:
T1_id | T2_id | T3_id
1 1 3
2 1 4
3 2 3
I tried:
select T3.id
from T1
left join T2 on T2.id = T1.T2_id
right join T3 on T3.id != T1.T3_id
where T2.id = 1
the output is:
1
2
3
1
2
4
It should be only 1 and 2. What am I missing? It works fine with T2.id = 2.
You can also do this like that
select T3.id from T1, T2, T3
where
T1.T2_id = T2.id and
T3.id <> T1.T3_id and
T2.id = 1
I hope this helps
So you have
List of clients
List of suppliers
A map between clients and suppliers.
This should be your table layout.
clients
---------
client_id [PK]
client_label
suppliers
---------
supplier_id [PK]
supplier_label
client_suppliers
----------------
client_supplier_id [PK]
client_id
supplier_id
Then you just select which suppliers are mapped to a particular client.
SELECT
supplier_id
, supplier_label
FROM
suppliers T1
INNER JOIN
client_suppliers T2 ON T2.supplier_id = T1.supplier_id
WHERE
T2.client_id = 1

How to select rows not present in another table with 2 columns comparison?

I have the following tables:
T1 T2 Desired result
CA CB CA CC CA CB
1 2 1 3 1 4
1 4 1 2 2 1
1 3 1 5 2 3
2 1 2 4
2 3
3 6
3 1
4 ...
I need to make a join between T1 and T2 (using column CA) and return only those rows which the values in CB do not exists in T2.CC
A simple way to achieve that is using the following query:
SELECT T1.* FROM T1 INNER JOIN T2 ON t1.CA = t2.CA AND
t1.CB NOT IN (SELECT CC FROM T2 WHERE T2.CA = T1.CA)
I think the previous query is not very efficient. For that reason I am looking for something better
Any help will be appreciated
Generally, a more efficient means of achieving this sort of result is finding records which fail a simpler join condition. Those can be found by doing an outer join and checking for null, as follows:
select t1.ca, t1.cb
from t1 left outer join t2 on t1.ca=t2.ca and t1.cb=t2.cc
where t2.ca is null;
I think you just want not exists:
select t1.*
from t1
where not exists (select 1
from t2
where t2.ca = t1.ca and t2.cb = t1.cb
);
For performance, you want an index on t2(ca, cb).

MS Access Joining Three tables on same field

I have the following tables
t1: t2: t3:
id id f1 id f2
1 1 a 3 a
2 2 b 4 b
3 3 c 5 c
4
5
and I am trying to get the following result
t4:
id f1 f2
1 a
2 b
3 c a
4 b
5 c
I am using the following query
SELECT t1.id, t2.f1, t3.f2
FROM (t1
LEFT JOIN t2 ON t1.id = t2.id) AS a
LEFT JOIN t3 ON t1.id = t3.id
It works but the query takes a while to run. Is there a better way to do this? Thanks
To offer an alternative which doesn't involve additional tables: you could perhaps try structuring the SQL to perform a nested SELECT query such that only tables are joined for each SELECT query, but I doubt that this would offer a drastic improvement over what you have:
SELECT tmp.id, tmp.f1, t3.f2
FROM
(SELECT t1.id, t2.f1 FROM t1 LEFT JOIN t2 ON t1.id = t2.id) AS tmp
LEFT JOIN t3 ON tmp.id = t3.id

SQL Full Outer Join W/ Coalesce

Why does this query produce duplicates in some scenarios?
Table_1
ID
1
2
3
Table_2
ID
1
2
4
Table_3
ID
1
3
4
Query:
SELECT COALESCE(Table_1.ID, Table_2.ID, Table_3.ID)
FROM Table_1
FULL OUTER JOIN TABLE_2
ON Table1.ID=Table_2.ID
FULL OUTER JOIN TABLE_3
ON Table1.ID=Table3.ID;
Result:
1
2
3
4
4
The query duplicates all values where T1 is null and T2/T3 share the same value. Duplicates are removed for any other combination.
This is a little bit hard to explain. If you show the other ids, you will see the full range of what happens:
"coalesce" "id1" "id2" "id3"
1 1 1 1
2 2 2 .
3 3 . 3
4 . 4 .
4 . . 4
You can see the results here.
So, You get one row because t1 & t2 create a row with t2.id = 4 and t1.id = null when they don't match. Then, you get the same thing when t3.id = 4. The comparison is to t1.id -- so you get another row. There is no comparison to t2.id.
I suspect that you intend logic more like this:
select coalesce(t1.id, t2.id, t3.id)
from t1 full join
t2
using (id) full join
t3
using (id);
Here is the SQL Fiddle.

postgreSQL Duplicate rows counting on join

I have one complicated question. I'll try to explain it with example:
have one table that have primary key, and I want to join other table there the first's table primary key is foreign key, and I want If in the second table there is duplicate foreign key to select the number of repeatability. For example:
1-st table:
id name
--- -----
1 Greg
2 Alan
3 George
4 John
5 Peter
2-nd table
id aid data
--- ----- -------
1 2 CCCV
2 2 VVVV
3 3 DDDDD
4 3 SSSS
5 4 PPPPP
I want the result of the join to be:
id(1st table) aid name Data Number
----------- ---- ----- ----- -----
1 null Greg null 1
2 1 Alan CCCV 1
2 2 Alan VVVV 2
3 3 George DDDDD 1
3 4 George SSSS 2
4 5 John PPPPP 1
5 null Peter null 1
I searched a lot, I couldn't find anything. Maybe I do not know how search, or there is no such thing as what I want to do.
SELECT Table1.id, Table2.id as aid, Table1.name, Table2.data,
GREATEST(1, (SELECT COUNT(*)
FROM Table2 t2
WHERE t2.aid = Table1.id
AND t2.id <= Table2.id))
AS number
FROM Table1
LEFT JOIN Table2
ON Table2.aid = Table1.id
ORDER BY id, aid;
works in both MySQL and PostgreSQL.
As per my comment, you've tagged this both MySQL and PostgreSQL.
This answer is for PostgreSQL.
SELECT
table1.id,
table2.aid,
table1.name,
table2.data,
ROW_NUMBER() OVER (PARTITION BY table1.id ORDER BY table2.aid) AS number
FROM
table1
LEFT JOIN
table2
ON table1.id = table2.aid
Queries for PostgreSQL 8.3 which has no window functions.
With bigger tables it is regularly much faster to use a JOIN instead of a correlated sub-query.
The first query aggregates values for Table2 before joining to Table1, which should befaster, too:
SELECT t1.id, t2.aid, t1.name, t2.data, COALESCE(t2.ct, 1) AS number
FROM Table1 t1
LEFT JOIN (
SELECT x.aid, x.data, count(y.aid) + 1 AS ct
FROM Table2 x
LEFT JOIN Table2 y ON x.aid = y.aid AND x.id > y.id
GROUP BY x.aid, x.data
) t2 ON t2.aid = t1.id
ORDER BY t1.id, t2.ct;
And ORDER BY should be fixed.
Alternative without sub-query. Might be faster, yet:
SELECT t1.id, t2.aid, t1.name, t2.data, count(*) + count(t3.id) AS number
FROM Table1 t1
LEFT JOIN Table2 t2 ON t2.aid = t1.id
LEFT JOIN Table2 t3 ON t3.aid = t2.aid AND t3.id < t2.id
GROUP BY t1.id, t2.aid, t1.name, t2.data
ORDER BY t1.id, count(t3.id);
Not sure, didn't test with a bigger set. Test performance with EXPLAIN ANALYZE. Could you report back your results?