MySQL LEFT RIGHT JOIN syntax fluency - mysql

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)

Related

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 ...

How does multiple "ON" in a JOIN statement works

I'm currently reading a query that I don't usually see in some other queries when joining tables.
SELECT
*
FROM table_1
RIGHT OUTER JOIN table_2
INNER JOIN table_3
ON table_2.some_id = table_3.some_id
RIGHT OUTER JOIN table_4
ON table_3.some_id = table_4.some_id
LEFT OUTER JOIN table_5
ON table_4.some_id = table_5.some_id
ON table_1.some_id = table_4.some_id
Please don't mind how those tables being joined. I just want to know how did that query works? Thank you in advance.
I think the SQL Server documentation captures what is happening better than MySQL. (Here is the documentation.)
This is a parsing issue, as Laurence has observed. You can understand what is by looking at the syntax diagram for the from statement. There is a recursive reference that most people never think about (including me). A joined table has the following syntax:
<joined_table> ::=
{
<table_source> <join_type> <table_source> ON <search_condition>
| <table_source> CROSS JOIN <table_source>
| left_table_source { CROSS | OUTER } APPLY right_table_source
| [ ( ] <joined_table> [ ) ]
}
The key here is the first piece, <table_source> <join_type> <table_source>. Well, guess what, a table_source can be a joined_table (as well as a bunch of other things). This means that the syntax:
A join B join C ON <condition1> ON <condition2>
Fits the grammar above and is interpreted as:
A join (B join C on <condition1>) ON <condition2>
That is, the expression B join C on <condition1> is treated as a "table_source".
My guess is that if both SQL Server and MySQL do it this way, then it is probably part of the standard. However, the standard is a bit harder to understand than SQL Server's syntax diagrams.
I think this is down to the way right outer join is evaluated:
Select
*
from
a
right outer join
b
inner join
c
on b.id = c.id
on a.id = b.id;
is evaluated as
Select
*
from
a
right outer join (
b
inner join
c
on b.id = c.id
)
on a.id = b.id;
Mixing left and right outer join is a path to madness.
The OP's query seems to be driven by a desire to exclude parenthesis, or derived tables. It is equivalent to:
Select
a.id ida,
b.id idb,
c.id idc,
d.id idd,
e.id ide
From
D
left outer join
A
on d.id = a.id
left outer join
E
on d.id = e.id
left outer join (
B
inner join
C
on b.id = c.id
)
on d.id = b.id;
Example SQLFiddle

Join MySQL tables based on condition?

Problem:
I'm trying to figure out how to join tables based on a condition in an SQL statement. I've spent an hour searching Google, SO, various websites and the MYSQL manual, but I just can't find the correct syntax for what I want to do.
I can't post the exact query I'm trying to get working, but I will post a simplified version for simplicity reasons.
Scenario:
Assuming I have three tables, a = person table, b = address table and c = car table.
Table b will always be joined to table a, becuase a person always lives at an address, but table c should only be joined to a if the value in the 'car_id' field is more than 0, because having a car is optional.
The query:
SELECT a.firstname, a.lastname, a.gender, a.address_id, b.address_firstline, b_address_secondline, b.postcode, c.car_manufacturer, c.car_model
FROM a
INNER JOIN b ON b.id = a.address_id
INNER JOIN c ON c.id = a.car_id AND a.car_id > 0
WHERE a.id = 1
The query above will run fine for a person with the id of 1 because he owns a car. However, if the query is run for a person with the id of 2, the query will return 0 rows because she does not own a car.
How do I make this second JOIN optional? I've tried using the IF ELSE statement, but I'm forever getting syntax errors. Could someone point me in the right direction here? Thanks in advance
You should use left outer join to join c with a.
SELECT a.firstname, a.lastname, a.gender, a.address_id, b.address_firstline, b_address_secondline, b.postcode, c.car_manufacturer, c.car_model
FROM a
INNER JOIN b ON b.id = a.address_id
LEFT OUTER JOIN c ON c.id = a.car_id AND a.car_id > 0
WHERE a.id = 1
Use LEFT JOIN instead of INNER JOIN on table c.
Unilateral joins work on this scenario.
A brief explanation.
a INNER JOIN b ON a.field1 = b.field1 returns every row for which both a.field1 and b.field1 exist and are equal
a LEFT JOIN b ON a.field1 = b.field1 returns every row from table a and returns every row in table b for which a.field1 = b.field1, and null values for non-matching values on table b.
RIGHT JOIN is analogous to LEFT JOIN

Mysql inner joins advanced, howto

Can anyone help me with this query?
I have three tables (A;B;C)
A <--1....N---> B <--1....N---> C
I want all A rows having C.dates (the greatest)
SELECT A.*, MAX(C.dates)
FROM A
JOIN B ON B.A_fk = A.id
JOIN C ON C.B_fk = B.id
GROUP BY A.id
This JOIN will exclude results which wont have LEFT join. That is, if any row from A wont have B row or any row from B wont have any C row, then the row wont show. To overcome this you can use LEFT JOIN instead of JOIN.
SELECT A.*, MAX(C.dates)
FROM A
LEFT JOIN B ON B.A_fk = A.id
LEFT JOIN C ON C.B_fk = B.id
GROUP BY A.id
EDIT: Sorry didnt noticed that you needed the greatest value of C.data. There you have it. You have to use MAX function in SELECT and GROUP BY A.id