Multi table joins - can I add an outer join to this? - sql

I'm having a problem moving from a situation where an Outer Join works, to where it fails.
Working (pseudo code example)
SELECT a.number, a.name, b.ref, c.ref, c.firmref
FROM jobs a, teams b LEFT OUTER JOIN teamfirms c ON b.ref = c.team
WHERE a.ref = b.job
There is a many to one relationship between jobs and teams (many teams per job) that is always populated
There may or may not be firms in table c, but the query above gives me the result I would expect (approx 5000 records)
The problem comes when I want to bring in the details about the teams from a fourth table
The code I am trying is below
SELECT a.number, a.name, b.ref, c.ref, c.firmref, d.name
FROM jobs a, teams b LEFT OUTER JOIN teamfirms c ON b.ref = c.team, firms d
WHERE a.ref = b.job
AND d.ref = c.firmref
At this point the NULLS that I am trying to capture disappear and I drop approx 500 records
What am I doing wrong?

take a whack at this.
select a.number, a.name, b.ref, c.ref, c.firmref, d.name
from jobs a left outer join teams b on b.job = a.ref
left outer join teamfirms c on b.ref = c.team
left outer join firms d on c.firmref = d.ref
left outer join table e on a.column = e.column
or you could do
select a.number, a.name, b.ref, c.ref, c.firmref, d.name
from
jobs a, teams b, teamfirms c, firms d
where
a.ref = b.job
and b.ref = c.team
and c.firmref = d.ref
one or the other... not both.
Just to throw this in for good measure...
You use INNER JOIN to return all rows
from both tables where there is a
match. ie. in the resulting table all
the rows and colums will have values.
LEFT OUTER JOIN returns all the rows
from the first table, even if there
are no matches in the second table.
RIGHT OUTER JOIN returns all the rows
from the second table, even if there
are no matches in the first table.

You are mixing ANSI 89 and 92 JOIN syntax (implicit and explicit JOINs). Try converting the entire query to explicit JOINs. The problem is likely that the new JOIN you're adding (implicit syntax) is INNER and wants to be OUTER, or that you want to resolve the JOINs in a different order (which you can do with parens once you write them all as OUTER JOINs)

Try, the following:
SELECT
a.number, a.name, b.ref, c.ref, c.firmref, d.name
FROM
jobs a, teams b
LEFT OUTER JOIN teamfirms c ON b.ref = c.team
LEFT OUTER JOIN firms d on c.firmref = d.ref
WHERE a.ref = b.job
If it works, you could then try to turn the 2nd LEFT OUTER into an INNER. Possibly incorrectly I've generally left it as an outer when I've needed this sort of thing.

Here is my attempt:
SELECT a.number, a.name, b.ref, c.ref, c.firmref, d.name
FROM jobs a
join teams b on (b.job = a.ref)
LEFT OUTER JOIN teamfirms c ON (b.ref = c.team)
LEFT OUTER JOIN firms d on (d.ref = c.firmref)
This will join all jobs to team and if a teamfirm exist then also bring firm details. if no team firm relationship you still get your nulls.

Try the following:
SELECT a.number, a.name, b.ref, c.ref, c.firmref, d.name
FROM jobs a, teams b LEFT OUTER JOIN teamfirms c ON b.ref = c.team
LEFT OUTER JOIN firms d ON c.firmref = d.ref
WHERE a.ref = b.job

Related

Column '' in field list is ambiguous. (when JOIN ON)

Column 'company_id' in field list is ambiguous
It does not seem "ambiguous", I have no idea where I should fix it:
SELECT company_id, companies.name
FROM company_contracts AS contracts
LEFT OUTER JOIN companies ON companies.id = contracts.company_id
LEFT OUTER JOIN order_logs AS logs ON companies.id = logs.company_id;
Because company_id appears on both table company_contracts and order_logs,you need to specify it
SELECT contracts.company_id,c1.name
FROM company_contracts as contracts
LEFT OUTER JOIN companies as c1 on c1.id = contracts.company_id
LEFT OUTER JOIN order_logs as logs on c1.id = logs.company_id;
You should qualify all columns names in such a query. In addition, if you really want outer joins, the second join condition should refer to the first table, not the second:
SELECT cc.company_id, c.name
FROM company_contracts cc LEFT OUTER JOIN
companies c
ON c.id = cc.company_id LEFT OUTER JOIN
order_logs ol
ON cc.company_id = ol.company_id;
Or, more likely, you want to keep all companies and the query should look like:
SELECT c.id, c.name
FROM companies c LEFT OUTER JOIN
company_contracts cc
ON c.id = cc.company_id LEFT OUTER JOIN
order_logs ol
ON c.id = ol.company_id;

Multiple joins with group by (Sum)

When I using multiple JOIN, I hope to get the sum of some column in joined tables.
SELECT
A.*,
SUM(C.purchase_price) AS purcchase_total,
SUM(D.sales_price) AS sales_total,
B.user_name
FROM
PROJECT AS A
LEFT JOIN
USER AS B ON A.user_idx = B.user_idx
LEFT JOIN
PURCHASE AS C ON A.project_idx = C.project_idx
LEFT JOIN
SALES AS D ON A.project_idx = D.project_idx
GROUP BY
????
You need to use subquery as follows:
SELECT A.project_idx,
a.project_name,
A.project_category,
sum(C.purchase_price) AS purcchase_total,
sum(D.sales_price) as sales_total,
B.user_name
FROM PROJECT AS A
LEFT JOIN USER AS B ON A.user_idx = B.user_idx
LEFT JOIN (select project_idx, sum(purchase_price) as purchase_price
from PURCHASE group by project_idx ) AS C ON A.project_idx = C.project_idx
LEFT JOIN (select project_idx, sum(sale_price) as sale_price
from SALES group by project_idx) AS D ON A.project_idx = D.project_idx
I am not sure but you can use inner join of project with user instead of left join.
SELECT A.project_idx,
a.project_name,
A.project_category,
purcchase_total,
sales_total,
B.user_name
FROM PROJECT AS A
LEFT JOIN USER AS B ON A.user_idx = B.user_idx
LEFT JOIN (select project_idx, sum(purchase_price) as purchase_total
from PURCHASE group by project_idx ) AS C ON A.project_idx = C.project_idx
LEFT JOIN (select project_idx, sum(sale_price) as sale_total
from SALES group by project_idx) AS D ON A.project_idx = D.project_idx
This is working correctly on MS-SQL Server.
Thanks to Popeye
You are attempting to aggregate over two unrelated dimensions, and that throws off all the calculations.
Correlated subqueries are an alternative:
SELECT p.*,
(SELECT SUM(pu.purchase_price)
FROM PURCHASE pu
WHERE p.project_idx = pu.project_idx
) as purchase_total,
(SELECT SUM(s.sales_price)
FROM SALES s
WHERE p.project_idx = s.project_idx
) as sales_total,
u.user_name
FROM PROJECT p LEFT JOIN
USER u
ON p.user_idx = u.user_idx ;
Note that this uses meaningful table aliases so the query is easier to read. Arbitrary letters are really no better (and perhaps worse) than using the entire table name.
Correlated subqueries avoid the outer aggregation as well -- and let you select all the columns from the first table, which is what you want. They also often have better performance with the right indexes.

SQL Server Circular Query

I have 4 tables, in that I want to fetch records from all 4 and aggregate the values
I have these tables
I am expecting this output
but getting this output as a Cartesian product
It is multiplying the expenses and allocation
Here is my query
select
a.NAME, b.P_NAME,
sum(a.DURATION) DURATION,
sum(b.[EXP]) EXPEN
from
(select
e.ID, a.P_ID, e.NAME, a.DURATION DURATION
from
EMPLOYEE e
inner join
ALLOCATION a ON e.ID = a.E_ID) a
inner join
(select
p.P_ID, e.E_ID, p.P_NAME, e.amt [EXP]
from
PROJECT p
inner join
EXPENSES e ON p.P_ID = e.P_ID) b ON a.ID = b.E_ID
and a.P_ID = b.P_ID
group by
a.NAME, b.P_NAME
Can anyone suggest something about this.
The following should work:
SELECT e.Name,p.Name,COALESCE(d.Duration,0),COALESCE(exp.Expen,0)
FROM
Employee e
CROSS JOIN
Project p
LEFT JOIN
(SELECT E_ID,P_ID,SUM(Duration) as Duration FROM Allocation
GROUP BY E_ID,P_ID) d
ON
e.E_ID = d.E_ID and
p.P_ID = d.P_ID
LEFT JOIN
(SELECT E_ID,P_ID,SUM(AMT) as Expen FROM Expenses
GROUP BY E_ID,P_ID) exp
ON
e.E_ID = exp.E_ID and
p.P_ID = exp.P_ID
WHERE
d.E_ID is not null or
exp.E_ID is not null
I've tried to write a query that will produce results where e.g. there are rows in Expenses but no rows in Allocations (or vice versa) for some particular E_ID,P_ID combination.
Use left join in select query by passing common id for all table
Hi I got the answer what I want from some modification in the query
The above query is also working like a charm and have done some modification to the original query and got the answer
Just have to group by the inner queries and then join the queries it will then not showing Cartesian product
Here is the updated one
select a.NAME,b.P_NAME,sum(a.DURATION) DURATION,sum(b.[EXP]) EXPEN from
(select e.ID,a.P_ID, e.NAME,sum(a.DURATION) DURATION from EMPLOYEE e inner join ALLOCATION a
ON e.ID=a.E_ID group by e.ID,e.NAME,a.P_ID) a
inner join
(select p.P_ID,e.E_ID, p.P_NAME,sum(e.amt) [EXP] from PROJECT p inner join EXPENSES e
ON p.P_ID=e.P_ID group by p.P_ID,p.P_NAME,e.E_ID) b
ON a.ID=b.e_ID and a.P_ID=b.P_ID group by a.NAME,b.P_NAME
Showing the correct output

SQL two multi-row counts in one query

I have got two queries:
select m.name, count(distinct a.kursnr)
from trainer t
left outer join mitarbeiter m
on t.svnr = m.svnr
left outer join einzeltraining e
on t.svnr = e.trainer
left outer join abhaltung a
on t.svnr = a.trainer
group by m.name, t.svnr;
select m.name, count(e.trainer)
from trainer t
left outer join mitarbeiter m
on t.svnr = m.svnr
left outer join einzeltraining e
on e.trainer = t.svnr
group by m.name, e.trainer;
The first one returns the correct number of courses (kursnr) and the second number the correct number of individual classes (einzeltraining) hold by a trainer. However, I cannot make one SQL statement which shows both values in one table. Any help would be appreciated. Thank you.
While there is likely a more efficient way to do this, I wanted to show you the easy way to combine any two queries that share a common field such as this:
select coalesce(q2.name, q1.name) As Name, q1.KursnrCount, q2.TrainerCount
from
( --original first query
select m.name, count(distinct a.kursnr) as KursnrCount
from trainer t
left outer join abhaltung a
on t.svnr = a.trainer
left outer join mitarbeiter m
on t.svnr = m.svnr
left outer join einzeltraining e on svnr = e.trainer
group by m.name, t.svnr
) q1
full join
( --original second query
select count(e.trainer) as TrainerCount, m.name
from trainer t
left outer join einzeltraining e
on e.trainer = t.svnr
left outer join mitarbeiter m
on t.svnr = m.svnr
group by e.trainer, m.name
) q2 on q2.name = q1.name
You could also use an inner join or left join, instead of a full join, depending on how the name fields from those queries match up.

JOIN syntax in MS ACCESS

I was tasked to create a new report on a legacy program. I needed to LEFT JOIN a table but I am getting Syntax error on JOIN Operation.
My SQL query as follows:
SELECT
SUM(b.qty) as qty,
b.price,
c.item_desc,
a.cust_name,
e.curr_symbol
FROM (
tran_hdr a,
tran_dtl b,
items c ,
tailoring e
(
LEFT JOIN
customers d
ON a.cust_name = d.name
)
)
WHERE a.tran_id = b.tran_id
AND b.item_no = c.item_no
GROUP BY b.price,
c.item_desc,
a.cust_name,
e.curr_symbol
I am joining the tran_hdr to customers. Because not all customers in Tran Header is maintained in customer table, but report requirest to show all Data in Transaction table.
You're messing up your JOINs.
And your Tailoring table has no relation whatsoever to other table.
So, just try this one out:
SELECT
b.price,
c.item_desc,
a.cust_name,
e.curr_symbol,
SUM(b.qty) as qty
FROM
tran_hdr a
INNER JOIN tran_dtl b
ON a.tran_id = b.tran_id
INNER JOIN items c
ON b.item_no = c.item_no
LEFT JOIN
customers d
ON a.cust_name = d.name
,tailoring e
GROUP BY b.price,
c.item_desc,
a.cust_name,
e.curr_symbol