Inner join on four tables on MySQL - mysql

I am trying to do an inner join on four tables in MySQL. The table names are:
question (id_question, question_text, id_standard)
standard (id_standard, standardtext)
organisation_standard(id_organisation,id_organisation,id_standard)
organisation (id_organisation, organisation_name)
This is my query and it's giving me repetitive values:
select distinct a.question_text, d.organisation_name
from question a
inner join standard b on a.id_standard = b.id_standard
inner join organisation_standard c on b.id_standard= c.id_standard
inner join organisation d on c.id_organisation = d.id_organisation
where a.id_standard = 18;
How can I avoid the repetitive values?

What you need is a left join and not an inner join change the inner joins into left joins and you will get just one row:
select distinct
a.question_text, d.organisation_name
from
question a
left join
standard b ON a.id_standard = b.id_standard
left join
organisation_standard c ON b.id_standard = c.id_standard
left join
organisation d ON c.id_organisation = d.id_organisation
where
a.id_standard = 18
group by a.id_standard;
This diagram from another so answer gives the difference between the different joins

Related

is there any way to control the order of joins in mysql?

currently the order is A left join B on ... left join C on ...
I want to add a column to B and C that is not present in A
is there a way to join B and C first including this join condition?
LEFT JOIN acts also as hidden STRAIGHT_JOIN, so the tables scanning order matches to their order in the FROM clause of the query text.
If you want join B to C firstly then you may set the joining order with parenthesis. For example, use not
FROM A
LEFT JOIN B on A.col1=B.col2
LEFT JOIN C on B.col3=C.col4
but
FROM A
LEFT JOIN (
B
LEFT JOIN C on B.col3=C.col4
) on A.col1=B.col2
or even (MySQL allows this syntax)
FROM A
LEFT JOIN (
B
LEFT JOIN C
) on A.col1=B.col2 AND B.col3=C.col4
You may also adjust the tables scanning order with Join-Order Optimizer Hints.

In MySQL JOIN means which join perform..?

It's to confusing, I have query where I have write JOIN with multiple table then which type of join it'll perform..?
For example :
SELECT
b.*
FROM
tbl_bookings b
JOIN tbl_users ua ON ua.id = b.act_id
JOIN tbl_users uc ON uc.id = b.cust_id
JOIN tbl_venue v ON b.venue_id = v.venue_id
WHERE
b.act_id = 4
Can any one please let me know by which type of join it'll perform..?
JOIN equals to an INNER JOIN . They are functionally equivalent, but INNER JOIN can be a bit clearer to read, especially if the query contains other type of JOIN
For something other than INNER JOIN you should specify the join you want.
LEFT JOIN / RIGHT JOIN which are the same as LEFT OUTER JOIN and RIGHT OUTER JOIN .
Those are just different ways of saying the same thing.
It will perform INNER JOIN. It is good to write INNER JOIN when you have different types of joins in query.

Left outer join and inner join on multiple tables in mysql

I need to replicate following where condition in Oracle to mysql.. I have also written my version of mysql query and I am having trouble writing left outer join part (I need to perform left outer on voters and join with nodes. Can someone please help?
Oracle equivalent:
WHERE B.nid=C.nid
AND B.uid = D.uid
and D.nid(+)= E.nid
Mysql query
select
C.ccc
,D.dewde
from
USERS B
inner join
ACCOUNT_GROUP_INFO C on (B.nid = C.nid)
inner join
VOTERS D on (B.uid = D.uid)
left outer join
NODES E on (D.nid = E.nid)
Can someone please help me with the query?

Cartesian join with multple outer joins to common root

I have the following schema.
I can run two queries fairly simply
select * from booking_model_assignment
join booking_model on booking_model_assignment.booking_model_id = booking_model.id
left outer join axis_channel_mappings on bmi_id = axis_channel_mappings.assignment_id
left outer join axis_revenue_stream_mappings on bmi_id = axis_revenue_stream_mappings.assignment_id
which will give me all of the combinations of channel mappings and 'revenue_stream_mappings' which fit a booking model, with Null if there is one which only matches in one of the tables.
The other query
select * from axis_channel join axis_revenue_stream
Gives all of the possible combinations of channels and revenue streams.
What I would like is a query which will give all of the combinations, and the booking_model if that combination matches.
Any time I try to join or subquery I seem to get too many, or too few results. I think the issue is that I want the assignment_id to match across outer joins but only if there is an outer join.
The schema is laid out like this so it will be possible to add new axis and fit models to combinations, so if there is an easier way to achieve this I would be open to changing the schema.
EDIT
I have a partial solution based on Eggyal's answer but it is not extendable.
SELECT c.*, r.*, GROUP_CONCAT(a.bmi_id), GROUP_CONCAT(b.name) AS booking_models
FROM axis_channel c
CROSS JOIN axis_revenue_stream r
LEFT JOIN axis_channel_mappings cm ON cm.channel_id = c.id
LEFT JOIN axis_revenue_stream_mappings rm ON rm.revenue_stream_id = r.id
LEFT JOIN booking_model_assignment a ON (a.bmi_id = cm.assignment_id
AND a.bmi_id = rm.assignment_id)
OR (a.bmi_id = cm.assignment_id
AND rm.assignment_id IS NULL)
OR (cm.assignment_id IS NULL
AND a.bmi_id = cm.assignment_id)
LEFT JOIN booking_model b ON b.id = a.booking_model_id
GROUP BY c.id, r.id
But if I were to add more axes this query would grow way to cumbersome.
SELECT c.*, r.*, GROUP_CONCAT(b.name) AS booking_models
FROM axis_channel c
CROSS JOIN axis_revenue_stream r
LEFT JOIN axis_channel_mappings cm ON cm.channel_id = c.id
LEFT JOIN axis_revenue_stream_mappings rm ON rm.revenue_stream_id = r.id
LEFT JOIN booking_model_assignment a ON a.bmi_id = cm.assignment_id
AND a.bmi_id = rm.assignment_id
LEFT JOIN booking_model b ON b.id = a.booking_model_id
GROUP BY c.id, r.id

mysql select statement not returning rows where some tables in query aren't populated

I'm having a real mind blank - This code selects rows quite nicely apart from those entries where I change st.station_id from a value of '1' to a different (but still valid) number but where there are no entries for that station_id in either the station_owner_map table, the organisation table or the cap_gen_data_table. I basically need to amend my sql to ignore any table where there are no entries.
Select st.station_id, st.station_name , st.st_town, st.st_state, c1.country_name, o1.organisation_name, som1.equity, st.river_basin, st.cost, st.cost_ref, st.comm_year,cg1.caporgen, ht1.hydro_name, cg1.value, srs1.srs_description, cg1.ref_year
FROM station st
inner join station_country_map scm1 on st.station_id = scm1.station_id
inner join country c1 on scm1.country_id = c1.country_id
inner join station_owner_map som1 on st.station_id = som1.station_id
inner join organisation o1 on som1.owner_id = o1.org_id
inner join cap_gen_data cg1 on st.station_id = cg1.station_id
inner join value_lookup vl1 on cg1.caporgen = vl1.id
inner join hydro_type ht1 on cg1.hydro_type_id = ht1.type_id
inner join station_record_status srs1 on cg1.capacity_status = srs1.st_rec_stat_id
where st.station_id = 1
It's caused by your inner joins. Inner join means there has to be a value in both tables for the record to show up in the result set.
Use left join instead, then only the table 'on the left' has to have a value.
Use left join on tables where the value may not be present.
If you have two tables A and B an inner join will only return the rows from A where the join condition is met. A left join will return all rows from A regardless of if the join condition is satisfied. Columns in the select statement associated with B will be null when a left join is used.
I have only added the left join to the tables you have indicated. If other tables may not satisfy the join condition change the join type from inner to left.
Select st.station_id, st.station_name , st.st_town, st.st_state, c1.country_name, o1.organisation_name, som1.equity, st.river_basin, st.cost, st.cost_ref, st.comm_year,cg1.caporgen, ht1.hydro_name, cg1.value, srs1.srs_description, cg1.ref_year
FROM station st
inner join station_country_map scm1 on st.station_id = scm1.station_id
inner join country c1 on scm1.country_id = c1.country_id
left join station_owner_map som1 on st.station_id = som1.station_id
left join organisation o1 on som1.owner_id = o1.org_id
left join cap_gen_data cg1 on st.station_id = cg1.station_id
inner join value_lookup vl1 on cg1.caporgen = vl1.id
inner join hydro_type ht1 on cg1.hydro_type_id = ht1.type_id
inner join station_record_status srs1 on cg1.capacity_status = srs1.st_rec_stat_id
where st.station_id = 1