Selecting Rows from one table based on conditions in two separate tables - mysql

I've tried using joins and wherein statements for the following but I either get a timeout because it's taking too long to run or I get duplicate column name error.
I have 3 tables:
A, B, C
I'd like to create a table consisting of rows from A based on constraints in B and C. So The row in A has to fulfill a condition in B OR C:
(A.ID = B.ID and A.PURCHASE = B.PURCHASE) OR (A.ID = C.ID AND A.PURCHASE = C.PURCHASE).
I've been using mysql for around... a week and this is the closest I've gotten(it hangs):
CREATE TABLE D
SELECT T1.*
FROM TABLE A AS T1, TABLE B AS T2, TABLE B AS T3
JOIN T2, T3 ON ((T1.CUSTOMER_ID = T2.CUSTOMER_ID AND T1.DAY_ID =
T2.DAY_ID) OR (T1.CUSTOMER_ID = T3.CUSTOMER_ID AND T1.DAY_ID = T2.DAY_ID));
Thanks for any help!

Join together A, B, and C using LEFT JOIN, and then retain records from A where a match occurred in either B or C.
INSERT INTO D
SELECT DISTINCT a.* -- remove duplicate records
FROM tableA a
LEFT JOIN tableB b
ON a.CUSTOMER_ID = b.CUSTOMER_ID AND a.DAY_ID = b.DAY_ID
LEFT JOIN tableC c
ON a.CUSTOMER_ID = c.CUSTOMER_ID AND a.DAY_ID = c.DAY_ID
WHERE b.CUSTOMER_ID IS NOT NULL OR -- retain records where either
c.CUSTOMER_ID IS NOT NULL -- condition matches
If the D table is not already created, then create it using the same definition as for table A.

Related

to fetch data from 2 tables

I am using MySQL to fetch data from 2 tables.
I want to fetch value 116 from column C of table 1 by matching column B of table 1 with column H of table2. If I apply join between the two, I get row second of table 1 as a result. But I want to get value 116 by matching values between the two. How can this be achieved in MySQL?
You seem to want a simple join:
select t2.*, t1.c
from table2 t2 join
table1 t1
on t2.h = t1.b;
You just need to specify the correct columns for lining up the two tables.
INNER JOIN will be good for you, like the following :
SELECT
table2.F as F, table1.A as A, table1.C as C
FROM table2
INNER JOIN table1
ON ( table1.B = table2.H )
or a LEFT JOIN in case C has a null value.
SELECT
table2.F as F, table1.A as A, table1.C as C
FROM table2
LEFT JOIN table1
ON ( table1.B = table2.H )

Joining two tables without a common column but using another table connected to both

I have three tables in Mysql
table A-> uid, itemType, balance,orderType
table B-> orderId, itemType, qty
table C-> uid,orderId
I need to get (balance-qty) for every uid:orderIdcombination for specific type of item. How can I connect table A and table B if they have no common column to join on. But both of them are connected to table C.
With joins between the 3 tables:
select a.uid, a.balance, b.qty
from tablea a
inner join tablec c on c.uid = a.uid
inner join tableb b on b.orderid = c.orderid
where a.itemtype = ?
You can add more columns if you need them.

How to join 3 tables where each has the key to the next in line

Imagine the following scenario:
There are 3 tables A, B and C.
Table A has no knowledge of either table B and table C.
Table B has a foreign key to table A.
Table C has foreign key to table B.
In table B as well as in table C there can be multiple items sharing the same foreign key value.
As you can see, the items from C are indirectly referenced to A through B.
What I want is to get all entries from A that are referenced in C but without any information from B or C in my result tables and without duplicates.
Is this even possible?
I have tried this like so but have no idea if it is correct:
select tableA.*
from tableA,
(select distinct tableB.AId as Aid
from tableB left join tableC on tableC.BId = tableB.id
group by tableB.id)
as temp
where tableA.id = temp.Aid
I am not sure if I understand it correctly, but you can try this one:
SELECT DISTINCT `A`.`id`, `A`.`value1`, `A`.`value2` FROM `A`
INNER JOIN `B` ON `B`.`id-a` = `A`.`id`
INNER JOIN `C` ON `C`.`id-b` = `B`.`id`
It returns all values from table A if there is a key on Table C which is linked to Table B with corresponding foreign key on table A
An alternative approach to Masoud's good response would be to use an exists though a correlated subquery.
The below subquery joins B to C in a correlated fashion (notice the B.IDA to A.ID and A is outside the subquery).
If we assume good database design, then A will not have duplicate records, thus we can omit a distinct here since we are not joining A to the other tables. Instead we are simply checking for the existence of an "A" record in the B table which must have a record in the C table due to the inner join. This has two advantages for performance
It doesn't have to join all the records together which would then
necessitate a distinct; thus you don't have the performance hit on
the distinct.
It can early escape. once a key value of A is found in the
subquery (B to C join) , it can stop looking and thus don't have to join all of B to all of A.
We select "1" in the subquery as we don't care what we select as the value will not be used anywhere. We're just using the coloration of A to (B JOIN C) to determine what in A to display.
SELECT A.*
FROM A
WHERE EXISTS( SELECT 1
FROM C
INNER JOIN B
on C.IDB = B.ID)
AND B.IDA = A.ID)
Taking what you tried and reviewing it:
select tableA.*
from tableA,
(select distinct tableB.AId as Aid
from tableB left join tableC on tableC.BId = tableB.id
group by tableB.id)
as temp
where tableA.id = temp.Aid
Starting with the "FROM"
You have tableA, (subquery) temp. This is a CROSS JOIN meaning all records from A will be joined to ALL records of (B JOIN C) so if you have 1000 records in A and 1000 records in the temp result then you'd be telling the database engine to generate 1000*1000 records in your result set; which then gets filtered to only include records matching in temp and A. The engine may be smart enough to avoid the cross join and optimize the query, but I find it confusing to maintain. So I would rewrite as
SELECT tableA.*
FROM tableA
INNER JOIN (SELECT distinct tableB.AId as Aid
FROM tableB left join tableC on tableC.BId = tableB.id
GROUP BY tableB.id) as temp
ON tableA.id = temp.Aid
Looking at the subquery (temp)
We don't need a group by as we are not aggregating. The distinct does bring us down to 1 record but at a cost to execution time.
So I would re-write as this:
SELECT tableA.*
FROM tableA
INNER JOIN (SELECT distinct tableB.AId as Aid
FROM tableB
LEFT JOIN tableC
on tableC.BId = tableB.id) as temp
ON tableA.id = temp.Aid
Then looking at the whole, if we change the outer query join to temp and make it an exists... using coloration we don't have the performance hit of the join, nor the distinct. and I'd switch the left join to an inner as we only want records in C and B so we'd have null in B if we left it as a "LEFT JOIN" which serve no purpose for us.
This gets me to the answer I initially provided.
SELECT tableA.*
FROM tableA
WHERE EXISTS (SELECT 1
FROM tableB
INNER JOIN tableC
on tableC.BId = tableB.id
AND tableB.AID = A.ID) as temp

mysql, SQL Inner join internals

I have 4 tables with schemas as below :
create table A
(
id int,
B_id int,
D_id int
);
create table B
(
id int,
C_id int
);
create table C
(
id int,
C_Parent_id int
);
create table C_Parent
(
id int
);
create table D
(
id int
);
In my case any row in A can be linked to a row in B / D and any row in B can be linked to a row in C & any row in C is definitely linked to a row in C_Parent.
I now insert some test data as below so that a row in table A is associated to a row in table B which is NOT associated to any row in table C.
I want to fetch some data from A , B(via A-> B link), D (A->D link) & C( if B->C link exists).
The problem is the query below does not work :
select A.id as Aid, B.id as bid, C.id as Cid, D.id as Did from
A inner join B on A.B_id = B.id
left outer join C on B.C_id = C.id
inner join C_Parent on C_Parent.id = C.C_Parent_id
left outer join D on A.D_id = D.id;
Perhaps because the inner join is getting applied on the entire result of join obtained till this point & not just on the row from table C as is described in the join condition (on C_Parent.id = C.C_Parent_id). Why is that?
I have modified above query to below query which works
select A.id as Aid, B.id as bid, C.id as Cid, D.id as Did from
A inner join B on A.B_id = B.id
left outer join
(
C inner join C_Parent on C_Parent.id = C.C_Parent_id
)on B.C_id = C.id
left outer join D on A.D_id = D.id
Q: Why is that?
A: When C.C_Parent_id is NULL, the equality comparison in the join condition
C_Parent.id = C.C_Parent_id
won't evaluate to TRUE, so a row is not returned, because it's an INNER JOIN operation.
And C.C_Parent_ID is going to be NULL anytime a row from B was returned when there wasn't a "matching" row from C.
Here's how I think about how the outer join operates. And this may help you understand what's happening.
For sake of example, consider
SELECT b.id
, c.b_id
FROM b
LEFT
JOIN c
ON c.b_id = b
This is going to return all rows from b, along with matching rows from c, just like an inner join, except,
(as you already know) if this were an inner join, when there isn't a matching row from c, the row from b won't be returned.
But with the OUTER JOIN, the row from b is returned.
So this is how I think about it...
When there isn't a matching row from c, the database conjures a dummy row to serve in the place of a matching row from c. The dummy row has all the same columns as c, but all of the columns in the dummy row have a value of NULL. And since there is now a "matching" row, the row from b can be returned.
So it's like an inner join except the database is generating a "dummy" row of NULL values to serve as a matching row.
I'm not sure if that helps you understand it. But that's how I got my brain wrapped around an "outer join" operation.
So in your example, when a dummy row from C gets conjured to satisfy the outer join, all of the columns from C are NULL. Which is why, when you get to the join condition ... C.C_Parent_ID is NULL.

Oracle Select Query based on Column value

I have two tables lets say
Table A
columns id , name address
Table B
columns id , age, import_date
The Table B id is a reference key of Table A.
Now I want to return results from A & B but if the record is not in B I still want to see the record so for this I use left outer join
Select * from A a left join B b
on a.id = b.id
Now even I don't have record in B I still get the record.
Table B may contain duplicate ids but unique import_date.
Now I want to results in a way that if there is duplicate id in table B then I want to get the records only where import_date is as of today.
I still want to get the records for ids which are not there but if the ID is there in table B then I want to apply above condition.
I hope someone can help me with this.
Sample data
Table A
01|John|London
02|Matt|Glasgow
03|Rodger|Paris
Table B
02|22|31-AUG-2015
02|21|30-AUG-2015
02|23|29-AUG-2015
The query will return
01|John|London|null|null|null
02|Matt|Glasgow|22|31-Aug-2015
03|Rodger|Paris|null|null
You almost got the solution. Just add one more condition like below
Select a.id,a.name,a.address,b.age,b.import_date
from tablea a left join tableb b
on a.id=b.id and b.import_date=trunc(sysdate)
order by a.id;---This line optional
Check the DEMO HERE
SELECT *
FROM Table_A t1 LEFT OUTER JOIN Table_B t2 ON t1.id=t2.id UNION
SELECT *
FROM Table_A t1 LEFT OUTER JOIN Table_B t2 ON t1.id=t2.id
GROUP BY t2.import_date
HAVING t2.import_date=CURDATE();