Full outer Join mySQL - missing rows - mysql

I am trying to emulate a full outer join in mySQL by using a left join and unioning it with a right join.
SELECT * FROM auxview_candiNotes AS a
LEFT JOIN auxview_clientNotes AS b ON a.dateAdded = b.dateAdded
UNION
SELECT * FROM auxview_candiNotes AS a
RIGHT JOIN auxview_clientNotes AS b ON a.dateAdded = b.dateAdded
The reason I am doing this is because I am joining two tables and occasionally one of them will not have a value on a specific date (thus the date is not listed in the table). However the joined table should display all dates, that occur in either or both of the tables. If one of the tables does not contain a value for a specific date, it should return NULL.
However, some dates from the auxview_clientNotes table are not listed in the joined table.
Thanks in advance!

This method isn't exactly a full outer join, because the union removes duplicates. Duplicates can be generated when the underlying tables have duplicates. Often duplicate removal is considered a "good" think, but the method is not exactly equivalent to a full outer join.
I prefer a left join approach:
select candi.*, client.*
from (select dateAdded from auxview_candiNotes union -- intentionally not `union all`
select dateAdded from auxview_clientNotes
) d left join
auxview_candiNotes candi
on candi.dateAdded = d.dateAdded left join
auxview_clientNotes client
on client.dateAdded = d.dateAdded;

Related

why is inner join causing query to show only results with not null column?

I'm running the query below and it is working well.
SELECT
stock_parts.title,
COUNT(*) as qtyAvailable,
SUM(shipments.item_cost) as totalValue,
### stock_alerts.minimum
FROM
stock_items
INNER JOIN stock_parts ON stock_items.stock_part_id = stock_parts.id
INNER JOIN shipments ON shipments.id = stock_items.shipment_id
### INNER JOIN stock_alerts ON stock_alerts.stock_part_id = stock_items.stock_part_id
WHERE
stock_items.status IS NULL
AND stock_items.current_stock_id = 1
GROUP BY stock_parts.id
So if I uncomment the two commented lines (is a join to get info from another table), the query results are filtered showing only rows where stock_alerts.minimum is not null.
Why is this happening? I need all results event that column is NULL.
What INNER JOIN does is output the row results where none of the tables have null values on that cell. In other words (from W3 Schools):
The INNER JOIN keyword selects records that have matching values in
both tables
Try using FULL OUTER JOINinstead to get all the records even when one of the tables has a NULL value on it. See the explanation on W3 Schools FULL OUTER JOIN.
EDIT:
I didn't realize one of your tags is MySQL. Here you have a post that explains how to emulate a FULL OUTER JOIN in MySQL
Inner JOIN will ignore NULLS when you do an equal to comparison, I would suggest using IS DISTINCT FROM OPERATOR (<=>)
stock_alerts.stock_part_id <=> stock_items.stock_part_id

select records from 3 tables with same column id

I am trying to write an SQL query which will select records of a student within 3 tables that have the same column_I'd.
This is what I wrote but the the records selected are not accurate:
select
Nov_DEC_billing.*,
Nov_DEC_students_portfolio.*,
admission_form.academic_year
from
Nov_DEC_billing,
Nov_DEC_student_portfolio,
admission_form
where
Nov_DEC_billing.ID = Nov_DEC_student_portfolio.ID=admission_form.ID
AND
admission_form.Program ='Nov/dec'
I get a records selected alright but its not accurate. Please what's the right way to join 3 tables that share the same column_id.???
Use JOIN in your query
SELECT b.*, p.*, a.academic_year
FROM Nov_DEC_billing b
JOIN Nov_DEC_student_portfolio p ON p.id = b.id
JOIN admission_form a ON a.id = b.id
WHERE a.Program='Nov/dec'
You need to join tables something like this:
SELECT Nov_DEC_billing.*,
Nov_DEC_students_portfolio.*,
admission_form.academic_year
FROM Nov_DEC_billing AS ndb,
LEFT JOIN Nov_DEC_student_portfolio AS ndsp ON ndsp.ID=ndb.ID,
LEFT JOIN admission_form AS af ON af.ID=ndb.ID
WHERE af.Program='Nov/dec'
You should join all the tables to a single one.
What you will is join all the tables to a single one and then select from it.
Since you have 2 tables you should first join 2 and then join another one on the result.
See here left join example for the exact syntax.
Nov_DEC_billing.ID=Nov_DEC_student_portfolio.ID=admission_form.ID
doesn't do what you expect. It takes the first part, Nov_DEC_billing.ID=Nov_DEC_student_portfolio.ID and evaluates it. If the values match, that part becomes a 1, if they don't match, it becomes 0. Then the 0 or the 1 is compared against admission_form.ID. That is very likely to give strange results.
So you'd have to split that into:
Nov_DEC_billing.ID=Nov_DEC_student_portfolio.ID
AND Nov_DEC_student_portfolio.ID=admission_form.ID
Or just use explicit join syntax, as the others already advised (and which I do too). That forces you to split this anyway.

MySQL Joins not working as required

I have two tables.
Table A:
root_id, root_text
Table B:
word_id , word_text,root_text
Now Some of the records of Table B has root_texts which might not exist in Table A.
So for that I am trying to use left join.
select *
from A a , B b
where a.root_text=+b.root_text
I only get the records which has matching root_text.
If I use the new way
Select
*
from
A left join B on a.root_text= b.root_text
I get so many extra records. I am Using MySQL 5.6.1.7
UPDATE :
http://sqlfiddle.com/#!9/7b32a/2
Query I am running
select * from word_detail w left join roots r
on r.root_text =w.root
and w.surah_no=1
and w.verse_no=1
and w.word_no=1
What I am doing wrong ?
As in result you see so many records which are not needed. The filter verse_no , word_no not working.
Update
The issue was after the left join we have to use where
select * from word_detail w left join roots r
on r.root_text =w.root
where w.surah_no=1
and w.verse_no=1
and w.word_no=1
If you want all records from TableB that are not present in table A you should use this:
Select *
from
B left join A
on a.root_text= b.root_text
where
a.root_text is null
or if you want the opposite - all records from tableA that are not present on tableB:
Select *
from
A left join B
on a.root_text= b.root_text
where
b.root_text is null
btw, this is not a left join on MySQL:
select * from A a , B b where a.root_text=+b.root_text
but will result as a simple INNER JOIN
The += operator is not standard SQL, but specific to the Oracle RDBMS, so it will not work as expected on MySQL.
The LEFT JOIN syntax is correct, the "many extra records" stem from the data in your tables. You might want to use some sort of WHERE as a filter or an aggregate to group the result set to make it more managable.
Your first example is an inner join which explains why you are not getting as many results as when you are left joining. Left joining can also be thought of as a left outer join.

How to create the inner query wtih 5 different tables mysql

Having 5 tables
Table a_dates = id,
Table b_types = id, a_date_id, c_type_id,
Table c_types = id, name,
Table d_profiles = id, name, profile_type
Table e_ps = id, a_date_id, d_profile_id
From a_dates Need to get b_types,...then from b_types needs c_types name,... Then compare c_types name with d_profiles name and get d_profiles id.... if equals then create a records in e_ps with a_date_id, d_profile_id.
Could any one please help me in getting the query from inner join.
I tried like, it is incomplete query
INSERT INTO e_ps(id,a_date_id,a_date_type,d_profile_id,c_id)
SELECT '',a.id,'A',dp.id,'67' FROM d_profiles dp
INNER JOIN a_dates a ON {HERE I NEED NAME MATCHING WITH c_types name} = dp.name and dp.profile_type = 'A'
INNER JOIN a_dates ON a.id = a_dates.id
LEFT OUTER JOIN e_ps eps ON eps.a_date_type = 'A' AND eps.a_date_id = a_dates.id
WHERE eps.a_date_id IS NULL
This seems to be a relatively simple JOIN:-
INSERT INTO e_ps(id, a_date_id, d_profile_id)
SELECT NULL, a_dates.id, d_profiles.id
FROM a_dates
INNER JOIN b_types ON a_dates.id = b_types.a_date_id
INNER JOIN c_types ON b.c_type_id = c.id
INNER JOIN d_profiles ON c_types.name = d_profiles.name
With joins there are several types, and I suspect you are getting confused. Briefly:-
With an INNER JOIN it looks for a match that is on BOTH tables. If no
match the no record is returned.
With a LEFT OUTER JOIN it takes a record from the table on the left
and looks for a match on the table on the right. If a match great,
but if not then it still brings a row back but the columns from the
table on the right just have values of NULL.
A RIGHT OUTER JOIN is very much the same, just with the tables
reversed (most people including me avoid using this as it has no
advantages most of the time but just makes things confusing).
With a FULL OUTER JOIN it gets the records from both side, whether
they match or not. If they match then the columns from both are
returned, if not matched then the columns from one are returned. Not
that MySQL does not support a FULL OUTER JOIN (although there are
ways to emulate it).
A CROSS JOIN joins every combination of 2 tables. These are used when
there is no common column to match on but you want all combinations.
For example if you wanted a table of all employees and all days of
the week for each employee you would cross join a table of days of
the week against a table of employees (then for useful data you might
LEFT OUTER JOIN a table of holidays to the result).

MySQL Union always returns one row with NULL's

Given the following query…
SELECT DISTINCT *
FROM PAS_Post
WHERE post_user_id = 21
GROUP BY post_post_id
UNION
SELECT DISTINCT PAS_Post.*
FROM PAS_Follow LEFT JOIN PAS_Post ON (
PAS_Follow.folw_followed_user_id = PAS_Post.post_user_id
)
WHERE PAS_Follow.folw_follower_user_id = 21
GROUP BY post_post_id
ORDER BY post_posted_date DESC
I always get a row in the results that is just NULL's, unfortunately I need to preserve some NULL values in the data as the Post's table (PAS_Post) holds different types of information.
Can anyone steer me in the right direction to get rid of this null row.
I do not want or need the last row here
You're using a (left) outer join in the second part of the UNION, so any cases that do not satisfy the join criteria will result in data from the table on the left of the join (PAS_Follow), but NULL in every column of the table on the right of the join (PAS_Post); the subsequent selection only of columns from the latter table results in the NULL rows that you observe. Therefore, the simplest solution is to use an inner join (that completely excludes records where the join criteria is not met).
However, in your case, it appears that your query can be greatly simplified by simply using two possible conditions in a filter on the joined tables rather than a UNION:
SELECT p.*
FROM PAS_Post AS p
JOIN PAS_Follow AS f ON f.folw_followed_user_id = p.post_user_id
WHERE p.post_user_id = 21
OR f.folw_follower_user_id = 21
ORDER BY p.post_posted_date DESC
I have excluded the GROUP BY clause on the assumption that post_post_id is the primary key (or at very least is UNIQUE) in your PAS_Post table. If that assumption is incorrect, you may want to reintroduce it—but beware that MySQL will indeterminately select the values that will be returned from each group.