I've been wrestling with this for a few hours and I'm hoping you can give me some fresh insight. I have 6 tables as follows:
Table A
Table B, which is a child of A (one-to-many)
Table C, which is a child of B (one-to-many)
Table D, which is a another child of A (one-to-many)
Table E is another parent of D, in a one-to-[zero-or-one] relationship
Table F, which is another child of E (one-to-many)
Basically I need to select a field from B where C = F.
I have tried with subqueries, joins, and a combination of both, but have not got too far. Any ideas would be appreciated.
With the information you've presented, how about
SELECT *
FROM A
INNER JOIN B ON B.AID = A.AID
INNER JOIN C ON C.BID = B.BID
INNER JOIN D ON D.AID = A.AID
INNER JOIN E ON E.DID = D.DID
INNER JOIN F ON F.EID = E.EID
WHERE C.Field = F.Field
If this is not what you need, you might want to post a small subset of data with the required results.
Related
There are 3 tables. Lets call them a, b and c. Selected data from table a must be intersected with b or c depending of value of one cell in table a. Lets call this cell d. Is there way in MySQL to make query like:
SELECT
a.cell,
a.other_cell,
a.d,
alias.cell,
alias.other_cell if(
a.d = 3,
left join b as alias on b.id = a.id,
left join c as alias on c.id = a.id
)
FROM
a where a.id = 123
You can try for example Conditional join as here but instead coalesce, use CASE WHEN
In short:
Instead, you simply LEFT OUTER JOIN to both tables, and in your SELECT clause, return data from the one that matches
select
E.EmployeeName,
CASE
WHEN d = 3 THEN s.store
WHEN d <>3 THEN o.office
END as Location
from
Employees E
left outer join
Stores S on …
left outer join
Offices O on …
NOTE I think the two columns must have the same type, at least in PG, not sure about MYSQL
Assuming you want select from the different tables (b and c) based on a 'cell' value in
table a then something like this work may work for you.
SELECT
a.cell,
a.other_cell,
a.d,
if(a.d = 3, b.cell, c.cell) cell
FROM a
INNER JOIN b on b.id = a.id
INNER JOIN c on c.id = a.id
WHERE a.id = 123
This should join the all 3 tables provided the id in b and c also match the id in table a. The if function will select the cell column from table b or c based on the value of column d in table a.
Also helpful: https://www.w3resource.com/mysql/control-flow-functions/if-function.php
$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.
I have 4 tables A, B, C & D as follows:
B belongs to A
B belongs to C
&
C has many D
As 'A' may or may not have any B's but if there is a B, then that B must have a C. And according to my logic, C will have at least one D or may be more.
Now, I want to get the list of A's with count(b) as well as count(d). Here count(b) and count(d) might be zero.
So what I was doing till now is as follows:
#a = A.joins(bs: {c: :ds}).select("a.*, count(b) as count_b, count(d) as count_d").group("a.id")
But eventually this is not working, as it INNER JOIN b with a. Which means, if there is no corresponding b for a, then that a will not be in the list #a. That's the problem.
So, is there any way to do it ?
joins has a form where it accepts a string. In that string you can put 'LEFT OUTER join bs ON bs... = as...'
Try Left outer join:
#a = A.joins("LEFT JOIN B on A.id=B.a_id INNER JOIN C on C.id=B.c_id INNER JOIN CD on C.id=CD.c_id INNER JOIN D on D.id=CD.d_id")
For more details check this question
I tried
#a = A.joins("LEFT JOIN B on A.id=B.a_id LEFT JOIN C on C.id=B.c_id LEFT JOIN CD on C.id=CD.c_id LEFT JOIN D on D.id=CD.d_id") which worked for me.
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 ...
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)