Reputation: 5
I have a few tables in my database:
user
table:user_id (primary key)
,first_name
,last_name
,email_address
.inst
table:inst_id (primary key)
,inst_name
, andtype
.user_insts
table:user_insts_id (primary key)
,user_insts_status
,inst_name (foreign key)
anduser_id(foreign key)
.
I'm using this on my website and i need it to display all of the entrys in the inst_name
column for the inst
table, but only the entrys for a certain id in the right side or else show as null. I've tried a few things like below:
SELECT inst.inst_name,inst.inst_id,user_insts.user_id,user_insts.inst_name
FROM inst LEFT JOIN user_insts ON inst.inst_name=user_insts.inst_name;
SELECT inst.inst_name,inst.inst_id,user_insts.user_id,user_insts.inst_name
FROM inst LEFT JOIN user_insts ON inst.inst_name=user_insts.inst_name
WHERE user_insts.user_id='11';
Any help would be greatly appreciated.
EDIT::
this is what i currently get:
inst_name inst_id user_id:
ASB 1 11
BNZ 3 11
FMG 5 11
i was hoping to be able to get something more like this:
inst_name inst_id user_id:
ASB 1 11
ANZ 2 NULL
BNZ 3 11
paymark 4 NULL
FMG 5 11
STATE 6 NULL
Upvotes: 0
Views: 168
Reputation: 3164
Do your provided queries show the following results?
inst
+ user_insts
entries but unfiltered by user_id
inst
+ user_insts
entries filtered by user_id
What's happening in Query 2 is that the where
clause filters the joined tables AFTER they are joined. I guess what you want to happen is to first filter the right side of the result (user_insts
) by a specific user_id
like so:
SELECT ui.inst_name, ui.user_id FROM user_insts ui WHERE ui.user_id = :PARAM
Then, you want to LEFT JOIN this with all the entries in the inst
table AFTER the filter. You could use an inner view in order to filter by user_id
first before the actual joining to the inst
table. The resulting query should be something like this:
SELECT i.inst_name, filtered_ui.user_id
FROM inst i
LEFT JOIN (SELECT ui.inst_name, ui.user_id
FROM user_insts ui
WHERE ui.user_id = :PARAM) filtered_ui
ON i.inst_name = filtered_ui.inst_name
Thinking about it more, I'm not too familiar with MySQL so I'm not sure if this alternative query is valid syntax:
SELECT i.inst_name, ui.user_id
FROM inst i
LEFT JOIN user_insts ui ON i.inst_name = ui.inst_name AND ui.user_id = :PARAM
... which may be simpler than an inner view.
The main point is you have to do the filtering first before joining, so that all the inst_names
will be displayed.
Upvotes: 0
Reputation: 18349
You question isn't 100% clear so I'm making the assumption that you want to show the inst_name for each user; showing the inst_name as null when an inst entry doesn't exist.
Something like this should work:
select u.user_id, i.inst_name
from user u
left join user_insts ui on ui.user_id = u.user_id
left join inst i on i.inst_name = ui.inst_name
You can constrain the results by user_id by adding
where u.user_id = '11'
Upvotes: 0
Reputation: 6096
What your original query will do is to get all rows from the inst
table and then see whether there is a row that matches on inst_name
in your user_insts
table. If there is it will return the data from that table. Otherwise it will return NULLs. If you change the JOIN to be an INNER JOIN then it will only return rows where the right-hand side matches. Like this:
SELECT inst.inst_name,inst.inst_id,user_insts.user_id,user_insts.inst_name
FROM inst INNER JOIN user_insts ON inst.inst_name=user_insts.inst_name
WHERE user_insts.user_id='11';
But you should look at changing you schema. You have an integer primary key on inst
so you should use that rather than inst_name
as the foreign key on inst_name
.
Upvotes: 1