Mysql inner join twice and use WHERE on both joins - mysql

In MySQL, I want to SELECT A.* FROM A where an inner join condition is satisfied whether directly (joining table B) or through another join table (C), WHERE B.field = myvalue. Can anyone point out the proper way to get results?
I have the following tables: A, B, C, which are associated as follows (A joins B, B joins C, A joins C):
B
/ \
A --- C
It looks pretty straightforward, but I get an empty set when I run the following code, even though I get results when I restrict the search to just joining B through C:
SELECT A.* FROM A
INNER JOIN C ON C.id = A.c_id
INNER JOIN B AS B_thru_C ON B_thru_C.id = C.b_id
INNER JOIN B AS B_from_A ON B_from_A.id = A.b_id
WHERE B_thru_C.field = 'myvalue' OR B_from_A.field = 'myvalue';
# yields an empty set
SELECT A.* FROM A
INNER JOIN C ON C.id = A.c_id
INNER JOIN B AS B_thru_C ON B_thru_C.id = C.b_id
WHERE B_thru_C.field = 'myvalue';
# yields results

How about this?
SELECT A.* FROM A
LEFT OUTER JOIN C ON C.id = A.c_id
INNER JOIN B ON B.id = A.b_id OR B.id = C.b_id
WHERE B.field = 'myvalue';

Related

SELECT JOIN with conditional (OR) cross

I need to do something like this (in MySQL), my attempts using UNION won't work until now.
In theory:
SELECT * FROM
tableA A
JOIN tableB B ON A.tableAId = B.tableAId
LEFT JOIN tableC C ON C.tableAId = A.tableAId
LEFT JOIN tableD D ON D.tableAId = A.tableAId
JOIN tableE E
ON (C.tableEId = E.tableEId OR D.tableEId = E.tableEId)
The expected result is crossing A with B, optional C with A, optional D with A and get the E result if its id is on C or D.
In order to know if the record found is from C or D, I'm using an IF checking if tableCId or tableDId are null.
I think your code will work.
SELECT *
FROM tableA A JOIN
tableB B
ON A.tableAId = B.tableAId LEFT JOIN
tableC C
ON C.tableAId = A.tableAId LEFT JOIN
tableD D
ON D.tableAId = A.tableAId JOIN
tableE E
ON E.tableEId IN (C.tableEId, D.tableEId);
This will filter out rows that have no matches in C and D, as well as those whose matches in C/D are not in E. I assume that is desirable.
Also, OR and IN can have a bad impact on JOIN performance, but you don't mention performance as a concern.

Need help writing an inner join query

$query= mysqli_query($db,"SELECT a.*, b.collection_id , c.contract_id,
d.customer_name FROM rentals_invoice
AS b INNER JOIN rental_collection as a ON (b.collection_id = a.collection_id)
AS c INNER JOIN rental_contract as b ON (c.contract_id = b.contract_id)
AS d INNER JOIN customer_info as c ON (d.customer_id = c.customer_id)");
I have tables a, b, c, d
'a' have fkey of 'b'
'b' have fkey of 'c'
'c' have fkey of 'd'
I want to get data from all of them, and I don't know how to get it through inner join or any other type of join in a single query.
I am a beginner.
You have misplaced your aliases. You are overwriting your aliases. You also can use the using to simplify this.
FROM rentals_invoice AS b
INNER JOIN rental_collection as a using(collection_id)
INNER JOIN rental_contract AS c using(contract_id)
INNER JOIN customer_info as d using(customer_id)");
I also would use aliases that relate to the actual table name. a, b, c, etc. aren't useful and will be hard to diagnose later.
$query = mysqli_query($db,"
SELECT a.*,b.collection_id,c.contract_id,d.customer_name
FROM `rentals_invoice` As a
INNER JOIN rental_collection As b ON b.collection_id = a.collection_id
INNER JOIN rental_contract AS c ON c.contract_id = b.contract_id
INNER JOIN customer_information AS d ON d.customer_cnic = c.customer_cnic
");
Thanks to all who helped or tried to help me, i got the understanding of JOIN.

MySQL with ON condition from another table

Let's say that I have:
SELECT * FROM a
LEFT OUTER JOIN b ON b.a_id = a.id
LEFT OUTER JOIN c ON b.c_id = c.id
Now what I want to do is to select b's that are assigned to c that is e. g. active (c.active = 1). How can I do that with ON?
Note that I can't use WHERE after the whole query above, because I want a's to be returned even if 0 b's are found.
Just to make sure, I understood the question: You want all rows where either c.active equals 1 or where there is no entry in b or c, right?
It's a bit lengthy but this seems to work:
SELECT * FROM a
LEFT OUTER JOIN b ON a.aid = b.aid
LEFT OUTER JOIN c ON b.bid = c.bid
WHERE a.aid NOT IN (
SELECT a.aid FROM a
INNER JOIN b ON a.aid = b.aid
INNER JOIN c ON b.bid = c.bid
WHERE NOT c.active
);
I could also imagine a solution using UNION
Which rows are returned in each case... Note that one case is different:
FROM b JOIN c ON ... AND c.active=1 -- rows in both tables exist and active
FROM b JOIN c ON ... WHERE c.active=1 -- ditto
FROM b LEFT JOIN c ON ... WHERE c.active=1 -- ditto
FROM b LEFT JOIN c ON ... AND c.active=1 -- all b's, but NULLs for inactive/missing c's
(Caveat: I am not sure I got the cases correct; just keep in mind that ON and WHERE are not always interchangeable.)
When mixing JOIN and LEFT JOIN, you may need to add parentheses:
FROM a JOIN ( b LEFT JOIN c ON... ) ON ... WHERE ...
FROM ( a JOIN b ON ... ) LEFT JOIN c ON... WHERE ...

MYSQL JOINS with 3 tables

TABLE A, B, C
How can I make a query that joins these three tables. The condition is that Table A must have a record.
I tried like this
select * from a
left join b on a.article_id = b.article_id
left join c on b.file_id = c.submission_id
where c.user_id = 6;
My query doesn't work in the case that Table C is missing a record. In that case, the join doesn't work for the three tables.
Any criteria on the outer tables must be int he relevant ON clause, not the WHERE clause.
For example:
select * from a
left join b on a.article_id = b.article_id
left join c on b.file_id = c.submission_id and c.user_id = 6;
If you use LEFT JOIN, then records from a and b are selected even if there are no corresponding records in table c. Use INNER JOIN instead:
SELECT * FROM a
INNER JOIN b ON a.article_id = b.article_id
INNER JOIN c ON b.file_id = c.submission_id
WHERE c.user_id = 6;

MySQL LEFT RIGHT JOIN syntax fluency

I'm coming across this situation alot, I'll have a query that will have one table needed in a join condition that may have no entries therefore requiring me to use a LEFT JOIN. I can't wrap my head around the syntax when it's used with more than 1 join.
I'll have:
SELECT A.*, B.*, C.*
FROM A, B, C
WHERE A.id = C.id
AND C.aid = A.id
AND B.cid = C.id
Along comes D with the possibility of being empty and I have to rewrite the query and run into problems.
How can I simply join D to any one of these tables?
You're much better off explicitly specifying all of your JOINs. That should make things much clearer.
SELECT A.*, B.*, C.*, D.*
FROM A
INNER JOIN C
ON C.aid = A.id
INNER JOIN B
ON B.cid = C.id
LEFT JOIN D
ON C.did = d.id
My advice is to never specify more than one column on FROM clause.
For clarity, it's better to always:
Use JOIN clause
Use aliases
Specify columns of joined tables on left side of equal sign
Example:
SELECT a.*, b.*, c.*
FROM ATable a
INNER JOIN BTable b
ON b.id = a.id
INNER JOIN CTable c
ON c.id = a.id
WHERE a.someColumn = 'something'
Not sure about MySQL, but in some other SQL flavors, you can use the same on UPDATES and DELETES, like:
DELETE FROM a
FROM ATable a
INNER JOIN BTable b
ON b.id = a.id
INNER JOIN CTable c
ON c.id = a.id
WHERE a.someColumn = 'something'
or
UPDATE a
SET something = newValue
FROM ATable a
INNER JOIN BTable b
ON b.id = a.id
INNER JOIN CTable c
ON c.id = a.id
WHERE a.someColumn = 'something'
The syntax below should help you. The basic premise is whatever table is listed LEFT is the required.. the table (or alias) on the right is optional. I understand you don't quite get it, and your syntax sample shows that (not meant to criticize) as you are joining from A -> C and C back to A on a different field. If this is the case where two fields are in the "C" table that BOTH point to A, you would re-join to A as a second alias...
select
Want.*,
Maybe.*,
SecondA.*,
B.*
From
A as Want
LEFT JOIN C as Maybe
on Want.ID = Maybe.ID
JOIN A as SecondA
on Maybe.AID = SecondA.ID
JOIN B
on Maybe.ID = B.cID
So, this query is stating I want everything from Table A (alias Want -- left side/first table in the list) Regardless of there being a match in Table C (alias Maybe) where the ID keys match.
Notice the next joins going down from "C" back to the second instance of "A" and table B. I have those as just joins... So the relationship between the "Maybe" alias, and that of second instance of "A" and "B" are JOIN (required).
Hopefully this gives some better clarification on HOW it works.
Now, for your real-life query. If you can describe what you are looking for, and your sample table structures / result expections, listing that could offer more explicit solution to your needs.
Hope this will help
SELECT
A.*, B.*, C.*
FROM A
inner join C on(A.id = C.id)
inner join B on(B.cid = C.id)