LEFT OUTER JOIN with no duplicates on left table - mysql

I've got two tables (let's say "left" and "right" tables). The right table's got from none to several rows matching each row on the left table.
I need to perform a query where I can join the two tables the same way a LEFT OUTER JOIN works, but getting only one row for each existing one in the left table. That row should be the one corresponding to the highest id on the right table.
A NATURAL JOIN would work, but I won't be getting the rows from the left table that don't match any row on the right one.

Try this:
Select L.[ValuesfromLeftTable], ...
R.[ValuesfromRightTable], ...
From LeftTable as L
Left Join RightTable as R
On R.Id = (Select Max(id)
From RightTable
Where FK = L.Id)

This is what I would do:
select *
from `left` as l
LEFT JOIN `right` as r
on (l.id = r.left_id)
group by l.id
order by r.id

You can use GROUP BY clause to show only distinct records

SELECT Left.Field1, Left.Field2, ... Right.Field1, Right.Field2, ...
FROM tblLeft AS Left
LEFT JOIN (SELECT CommonID, Max([ID]) AS MaxID
FROM tblRight
GROUP BY CommonID) AS RightMax ON Left.CommonID = RightMax.CommonID
LEFT JOIN tblRight AS Right ON RightMax.MaxID = Right.[ID] AND Left.CommonID = Right.CommonID

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.

Select MySQL Month() for null column

Got a question to ask. How do i get to list all of my left table to display the data when i use the left join even when some row got null value in it?
Heres my query:
SELECT *, SUM(transactions.debit_credit) current_spending
FROM (`budget`) LEFT JOIN `categories` ON `budget`.`category`=`categories`.`idcategory`
LEFT JOIN `user_category` ON `budget`.`category`=`user_category`.`idcategory`
LEFT JOIN `category_transaction` ON `budget`.`category`=`category_transaction`.`idcategory`
LEFT JOIN `transactions` ON `category_transaction`.`idtransaction`=`transactions`.`idtransaction`
WHERE `user_category`.`iduser` = '1'
AND MONTH(transactions.transaction_date) = '11'
GROUP BY `budget`.`idbudget`;
When I remove AND MONTH(transactions.transaction_date) = '11' the query works fine accept it displays all data instead of just 1 month of transaction.
Help?? Please?? Any idea how??
Your where clause turns your left join into an inner join because you filter the data on a condition of a joined table.
Instead put that condition in the on clause of your join
SELECT *, SUM(transactions.debit_credit) current_spending
FROM (`budget`)
LEFT JOIN `categories` ON `budget`.`category`=`categories`.`idcategory`
LEFT JOIN `user_category` ON `budget`.`category`=`user_category`.`idcategory`
AND `user_category`.`iduser` = '1'
LEFT JOIN `category_transaction` ON `budget`.`category`=`category_transaction`.`idcategory`
LEFT JOIN `transactions` ON `category_transaction`.`idtransaction`=`transactions`.`idtransaction`
AND MONTH(transactions.transaction_date) = '11'
GROUP BY `budget`.`idbudget`;

Select records where ID from one table is present in one or more other tables

OK, so I've found questions that cover how to do this with only two tables, tons of questions that explain how to do this if the ID does NOT exist in other tables, but not a solution to this query.
Basically, I have one table of wine vintages.
I then have four other tables that contain different types of content that is tied to a specific vintage (i.e. videos, blogs etc.)
I basically need to be able to pull a list of vintages that are in use i.e. where the vintage ID is used in one or more of the four content tables.
The closest I can get is this:
SELECT DISTINCT vintage_id FROM `pr_video_vintage`
INNER JOIN pr_video ON pr_video.fk_vintage_id = pr_video_vintage.vintage_id
INNER JOIN pr_reports ON pr_reports.fk_vintage_id = pr_video_vintage.vintage_id
INNER JOIN pr_reports_notes ON pr_reports_notes.fk_vintage_id = pr_video_vintage.vintage_id
INNER JOIN pr_blog_entries ON pr_blog_entries.fk_vintage_id = pr_video_vintage.vintage_id
ORDER BY `pr_video_vintage`.`vintage_id` ASC
But this (understandably I guess) only returns IDs that exist in ALL of the tables.
What I need is some form of 'OR' JOIN, but can't find any information out about how to go about doing this.
tips? :)
Try this:
SELECT distinct vintage_id FROM `pr_video_vintage`
where exists(select 1 from pr_video where pr_video.fk_vintage_id = pr_video_vintage.vintage_id)
or exists(select 1 from pr_reports where pr_reports.fk_vintage_id = pr_video_vintage.vintage_id)
or exists(select 1 from pr_reports_notes where pr_reports_notes.fk_vintage_id = pr_video_vintage.vintage_id)
or exists(select 1 from pr_blog_entries where pr_blog_entries.fk_vintage_id = pr_video_vintage.vintage_id)
or
SELECT distinct vintage_id FROM `pr_video_vintage`
where pr_video_vintage.vintage_id in (select pr_video.fk_vintage_id from pr_video)
or pr_video_vintage.vintage_id in (select pr_reports.fk_vintage_id from pr_reports)
or pr_video_vintage.vintage_id in (select pr_reports_notes.fk_vintage_id from pr_reports_notes)
or pr_video_vintage.vintage_id in (select pr_blog_entries.fk_vintage_id from pr_blog_entries)
or
SELECT distinct vintage_id FROM `pr_video_vintage`
where pr_video_vintage.vintage_id in (
select pr_video.fk_vintage_id from pr_video
union
select pr_reports.fk_vintage_id from pr_reports
union
select pr_reports_notes.fk_vintage_id from pr_reports_notes
union
select pr_blog_entries.fk_vintage_id from pr_blog_entries)
You can try using an OUTER JOIN or LEFT/RIGHT JOIN. OUTER JOIN computes the cartesian product of all entries including entries that are not present in both tables. LEFT JOIN shows everything in the table in the left hand side of the ON statement whether or not it exists in the right hand side, and RIGHT JOIN does the opposite.
Also, INNER JOIN is the same thing as JOIN if you want to save yourself some keystrokes!
You can run LEFT JOINs, which will return a NULL Id for nonexisting links, combined with a clause to exclude those rows which have all links NULLed.
SELECT DISTINCT vintage_id FROM `pr_video_vintage`
LEFT JOIN pr_video
ON pr_video.fk_vintage_id = pr_video_vintage.vintage_id
LEFT JOIN pr_reports
ON pr_reports.fk_vintage_id = pr_video_vintage.vintage_id
LEFT JOIN pr_reports_notes
ON pr_reports_notes.fk_vintage_id = pr_video_vintage.vintage_id
LEFT JOIN pr_blog_entries
ON pr_blog_entries.fk_vintage_id = pr_video_vintage.vintage_id
WHERE
pr_video.fk_vintage_id IS NOT NULL
OR
pr_reports.fk_vintage_id IS NOT NULL
OR
pr_reports_notes.fk_vintage_id IS NOT NULL
OR
pr_blog_entries.fk_vintage_id IS NOT NULL
ORDER BY `pr_video_vintage`.`vintage_id` ASC

Check id joining 3 tables

I have a MySQL JOIN query where 2 tables are joined to get the output
select distinct (a.error_type),a.links_id, a.crawl_cycle , b.* from $table a inner join crawler_error_type b on a.error_type = b.error_type where a.projects_id = '$pid' and b.error_priority_page_level='High'
Now I want to check if the value of the field error_type is present in the third table. If it is present then it shouldn't give me the resulted row.
Add the below:
LEFT OUTER JOIN third_table c ON c.error_type = a.error_type
and
WHERE c.error_type is null
LEFT OUTER JOIN will display all the records from a table joining on third_table. Since you do not want the record with matching error type from third_table, use WHERE c.error_type is null
You need to add one more INNER JOIN on third_table as:
SELECT DISTINCT a.error_type, a.links_id, a.crawl_cycle , b.*
FROM $table a
INNER JOIN crawler_error_type b
ON a.error_type = b.error_type
INNER JOIN third_table c
ON a.error_type = c.error_type
WHERE a.projects_id = '$pid' AND
b.error_priority_page_level='High'.
If I understand it correctly, you should just be able to inner join the third table. Inner joins will on show the record if they have records in the joining tables. If I am misunderstanding could you please elaborate. Thx
select distinct (a.error_type),a.links_id, a.crawl_cycle , b.*
from $table a
inner join crawler_error_type b on a.error_type = b.error_type
inner join some_table_3 c on c.error_type = a.error_type
where a.projects_id = '$pid' and b.error_priority_page_level='High'

How to join across 3 tables when one isn't a 'main' one

I wish to use a join across some tables but am having some difficulty finding a solution.
Take this SQL (stripped down):
SELECT
*
FROM project_contacts c
LEFT JOIN projects p ON c.project=p.ID
LEFT JOIN project_contact_type ON people.project_contact_type=project_contact_type.ID
LEFT JOIN people ON c.person=people.ID
WHERE p.live = 1
ORDER by p.code
LIMIT 4;
returns the error:
Unknown column 'people.project_contact_type' in 'on clause'
From the line:
LEFT JOIN project_contact_type ON people.project_contact_type=project_contact_type.ID
which is the issue, 'people.project_contact_type' is found based on the 'people' table and not the 'project_contacts' table which is the one where the other joins are off, if that makes sense??
So I don't know how to do a join inside of another join if thats even what I'm trying to do ;) ...
Order of the joins matters: the system doesn't know about the people, so it needs to be 2nd in your list.
SELECT
*
FROM project_contacts c
LEFT JOIN projects p
ON c.project=p.ID
LEFT JOIN people
ON c.person=people.ID
LEFT JOIN project_contact_type
ON people.project_contact_type=project_contact_type.ID
WHERE p.live = 1
ORDER by p.code
LIMIT 4;
Try this:
SELECT *
FROM project_contacts c
LEFT JOIN projects p ON c.project=p.ID
LEFT JOIN people ON c.person=people.ID
LEFT JOIN project_contact_type ON people.project_contact_type=project_contact_type.ID
WHERE p.live = 1
ORDER by p.code
LIMIT 4;