Left outer join to a generated table? - mysql

Am I on completely the wrong tack ?
I want to do a left outer join to a query generated from 2 tables , but i keep getting errors. Do I need a different approach?
t1:
ID, Surname,Firstname
t2:
ID,JobNo,Confirmed
I have the following query:
SELECT JobNo AS N, StaffID AS P, Confirmed as C,
FirstName AS F,Surname AS S
FROM gigs_players, Players
WHERE t1.StaffID=t2.StaffID AND JobNo="2"
AND (`Confirmed` IS NULL OR Confirmed ='Y' )
ORDER BY Instrument,Surname
I want to add:
LEFT OUTER JOIN contacted (ON t1.StaffID=contact.ID AND t2.JobNo=contact.JobNo)"
Can I do a left outer join to a query generated from 2 tables ?

In order to use the t1 and t2 in the left outer join that you want to add you need to join them with the first tables, you can't reference them directly in the left outer join you, Something like the following:
SELECT JobNo AS N, StaffID AS P, Confirmed as C,
FirstName AS F,Surname AS S
FROM gigs_players, Players
Inner join t1 on ...
Inner join t2 on ...
LEFT OUTER JOIN contacted c
on t1.StaffID=c.ID AND t2.JobNo = c.JobNo
WHERE t1.StaffID=t2.StaffID AND JobNo="2"
AND (`Confirmed` IS NULL OR Confirmed ='Y' )
ORDER BY Instrument,Surname
So, based in your tables' structure, define the conditions of the two joins with t1 and t2 with other tables.

Here is the an example of a left join to a sub query. This might be what you are looking for.
select
parts.id,
min(inv2.id) as nextFIFOitemid
from test.parts
left join
( select
inventory.id,
coalesce(parts.id, 1) as partid
from test.inventory
left join test.parts
on (parts.id = inventory.partid)
) inv2
on (parts.id = inv2.partid)
group by parts.id;

Related

Subtract count from left join and inner join in SQL

I want to merge two tables and subtract the number of orders in resulting table from left join from the resulting table in inner join.
This is what I have done but I do not know if this is correct or how to proceed?
WITH t1 AS (
SELECT *
FROM orders
LEFT JOIN food ON orders.id = food.id
),
t2 AS (
SELECT *
FROM orders
INNER JOIN food ON orders.id = food.id
)
SELECT
/* now what? */
Now I want to subtract number of rows in two tables.
I do not know how to proceed, should I join tables again and do subtraction, is there an easier way?
You don't even need two separate queries to answer your question. The only difference in result set between the left and inner joins is that the former will retain order records which do not map. So, you may simply write:
-- query #3
SELECT *
FROM orders o
LEFT JOIN food f
ON f.id = o.id
WHERE f.id IS NULL;
If you combine the result set from above with the inner join query #2, you will get the total left join query #1 result set without the WHERE clause.
So count(query #1) = count(query #2) + count(query #3)

Display name of foreign key column instead of its id

I have a match table whose structure is displayed here
in this table i have column teama, teamb which are a foreign key columns referenced to team table's t_id. Basically, what i want to do is that when i select all data from this table i want it to display the values in teama, and teamb instead of their t_id. Structure of Team table is here
Query which i am writing is below:
select *
from teams,matches
where
matches.team_a=teams.t_id
and matches.team_b=teams.t_id;
You need to join 2 columns of matches to the teams table:
select
m.m_id,
t1.t_name as team_a,
t2.t_name as team_b,
m.m_time
from
matches m inner join teams as t1 on m.team_a=t1.t_id
inner join teams as t2 on m.team_b=t2.t_id
order by m.m_id;
First, never use commas in the FROM clause. Always use proper, explicit, standard JOIN syntax. You need two JOINs in fact:
select m.*, ta.t_name as name_a, tb.t_name as name_b
from matches m left join
teams ta
on m.team_a = ta.t_id left join
teams tb
on m.team_b = tb.t_id;
This uses left join just to ensure that you get all matches, even if one of the teams is missing. In this case, that is probably not an important consideration, so inner join would be equivalent.
You want two INNER JOINs from table matches to table teams, like :
SELECT
ta.t_name,
tb.t_name
FROM
matches m
INNER JOIN team as ta on ta.t_id = matches.team_a
INNER JOIN team as tb on tb.t_id = matches.team_b
You can create view after join it was make your work simple for further developement,i was improove mr.forbas code as follow
CREATE VIEW team AS select
m.m_id,
t1.t_name as team_a,
t2.t_name as team_b,
m.m_time
from
matches m inner join teams as t1 on m.team_a=t1.t_id
inner join teams as t2 on m.team_b=t2.t_id
order by m.m_id;

Count of full outer join in mySQL

I'm trying to display the total number of rows in a full outer join table. I have the following code, but mysql says there is an error with duplicate columns. The 2 tables, actors and directors, have the same columns as they are supposed to provide similar information in their respective categories.
SELECT COUNT(*) FROM
(SELECT * FROM directors LEFT OUTER JOIN actors
ON directors.name = actors.name
UNION
SELECT * FROM directors RIGHT OUTER JOIN actors
ON directors.name = actors.name) AS table1;
What can be done to fix the code so it will run properly? FYI, the code from within the parenthesis runs fine. The problem only arises once I put in the SELECT COUNT(*) clause.
Becuase there are two name columns one is from directors table, another is from actors table, and you select * that will let DB engine confuse which name did you want to get.
if you only want to count total number you can try this.
SELECT COUNT(*) FROM
(
SELECT directors.name FROM directors LEFT OUTER JOIN actors
ON directors.name = actors.name
UNION
SELECT directors.name FROM directors RIGHT OUTER JOIN actors
ON directors.name = actors.name
) table1;
NOTE
I would suggest use select clear the columns and avoid using select *
It might be better to change the right join portion non-redundant, and just add separate
counts.
Generic version:
SELECT (SELECT COUNT(*) FROM A LEFT JOIN B ON A.x = B.x)
+ (SELECT COUNT(*) FROM B LEFT JOIN A ON B.x = A.x WHERE A.x IS NULL)
AS outerJoinSize
;
Note: I changed the RIGHT JOIN to a LEFT JOIN and swapped the tables around; in my experience, RIGHT JOIN just tends to make queries a little harder to read (especially when multiple joins are involved).
An completely different alternative...
SELECT
( SELECT SUM(dc1.c * IFNULL(ac1.c, 1)) AS jc
FROM (SELECT name, COUNT(*) AS c FROM directors GROUP BY name) AS dc1
LEFT JOIN (SELECT name, COUNT(*) AS c FROM actors GROUP BY name) AS ac1
ON dc1.name = ac1.name)
+ (SELECT SUM(IF(dc2.name IS NULL, ac2.c, 0)) AS jc
FROM (SELECT name, COUNT(*) AS c FROM actors GROUP BY name) AS ac2
LEFT JOIN (SELECT name, COUNT(*) AS c FROM directors GROUP BY name) AS dc2
ON ac2.name = dc2.name)
...this one figures out how many matches based on the joining field (3 instances of "Bob" in directors and 2 in actors means 6 join results for that name).
I'm not sure what you are getting at with the full join. But the best way to implement it in MySQL uses two left joins and a union:
select count(*)
from ((select name from directors) union -- on purpose
(select name from actors)
) da left join
directors d
on da.name = d.name left join
actors a
on da.name = a.name;
If I had to guess, though, you just want the number of distinct names between the two tables. If so:
select count(*)
from ((select name from directors) union -- on purpose
(select name from actors)
) da

Get only last record of JOIN in MySQL

I have 2 tables A, B where B contains a foreign key to A
ida,cola1
idb,fka,colb1
For each record from A I need to get only the last result of LEFT OUTER JOIN. The following query displays all JOINs, how to limit it to the last occurence of fka only?
SELECT ida,idb,cola1,colb1 FROM a LEFT OUTER JOIN b ON ida=fka
If the last result in table b is the one with the highest idb, then one solution is to use a subquery where you calculate max(idb) for each fka:
select
a.ida,
a.cola1,
b.idb,
b.fka,
b.colb1
from
a left outer join (
select fka, max(idb) as max_idb
from b
group by fka
) max_b on a.ida=max_b.fka
left outer join b on max_b.fka=b.fka and max_b.max_idb=b.idb
You can use group by to remove all other columns from the table B
then join the to the table A to get the result
Group by requires an aggregate function like min or max etc
Here I tried it with min
SELECT
ida, idb, cola1, colb1
FROM A LEFT OUTER JOIN (
select
min(idb) idb, fka, min(colb1) colb1
from B
group by fka
) b
ON ida = fka
SELECT
ida,idb,cola1,colb1
FROM a
LEFT OUTER JOIN b ON ida=fka
ORDER BY ida DESC LIMIT 1
May Be this one is Help you.

retrieve all record from one table and particular record from other

tbl_cmp
usr_id | cmp_name | usr_fname |cmp_addr
tbl_usr
cmp_usr_id |cmp_id | cmp_usr_fname | cnt_status
I am trying query retrieve data from both at a time for ::
retrieve all data from tbl_cmp
but
retrieve only field from tbl_usr that cnt_status=1
I tried this
SELECT *
FROM tbl_cmp
JOIN tbl_usr ON tbl_usr.cmp_id = tbl_cmp.usr_id
WHERE tbl_usr.cnt_status =1
but it shows only record that has cnt_status=1 not all record from first table
Try this
SELECT * FROM tbl_users LEFT JOIN tbl_cmp_user
ON tbl_cmp_user.cmp_id = tbl_users.usr_id
AND tbl_cmp_user.cnt_status =1
Use LEFT OUTER JOIN
SELECT *
FROM tbl_users
Left outer JOIN tbl_cmp_user
ON tbl_cmp_user.cmp_id = tbl_users.usr_id
and tbl_cmp_user.cnt_status =1
See Examples of left outer join here
What you really want is a cross join, because you do not have a join condition between the tables:
select c.*, u.*
from tbl_cmp c cross join
(select *
from tbl_users u
where u.cnt_status = 1
) u
You can express this without the subquery as:
select c.*, u.*
from tbl_cmp c cross join
tbl_users u
where u.cnt_status = 1
I prefer the subquery version, because it makes the condition on tbl_users quite apparent. In a more complicated query, the WHERE clause could be quite separated from where the table appears in the FROM clause.