outer join on junction table - sql

I'm using mssql
How do I do a outer join on three tables, one of which is a junction table?
There can be nulls in the menu or product tables and I need these included in the result.
SELECT *
from [web].[dbo].[tblMenus]
left outer JOIN [web].[dbo].[tblProductsRelMenus]
on [tblMenus].Id = [tblProductsRelMenus].MenuId
left outer JOIN [web].[dbo].[tblProducts]
on [tblProductsRelMenus].ProductId = [tblProducts].ProductId
This doesn't give menu nulls, and if I change the second left to a right, I loose the product nulls...
What is the correct way to do this?

Perhaps you are looking for a full outer join
SELECT *
from [web].[dbo].[tblMenus]
full outer JOIN [web].[dbo].[tblProductsRelMenus]
on [tblMenus].Id = [tblProductsRelMenus].MenuId
full outer JOIN [web].[dbo].[tblProducts]
on [tblProductsRelMenus].ProductId = [tblProducts].ProductId

SELECT *
FROM
[web].[dbo].[tblMenus]
LEFT JOIN
[web].[dbo].[tblProductsRelMenus]
RIGHT OUTER JOIN
[web].[dbo].[tblProducts]
ON [tblProductsRelMenus].ProductId = [tblProducts].ProductId
ON [tblMenus].Id = [tblProductsRelMenus].MenuId

Related

LEFT OUTER JOIN on 3 tables. Why does this SQL code give error 106

Why does the MySQL query below give error
1066 - Not unique table/alias: 'MOZ'
SELECT *
FROM GA, MOZ, SF
LEFT OUTER JOIN MOZ ON GA.Page = MOZ.URL
LEFT OUTER JOIN SF ON GA.Page = SF.Address
Simple rule: Don't use commas in the from clause:
SELECT *
FROM GA LEFT OUTER JOIN
MOZ
ON GA.Page = MOZ.URL LEFT OUTER JOIN
SF
ON GA.Page = SF.Address;
Your version was expressing a full cartesian product between the three tables and then trying to do the left joins. The specific problem was that the table aliases were ambiguous because they were defined twice in the from clause.
The error is pretty clear, you have referenced the table MOZ twice, choose another alias for the second table:
SELECT *
FROM GA, MOZ, SF
LEFT OUTER JOIN MOZ AS moz2 ON GA.Page = MOZ2.URL
LEFT OUTER JOIN SF ON GA.Page = SF.Address
Note that referencing the three table GA, MOZ, SF in the FROM clause this way will make them cross join and you will get a cartisian product, you have to add a JOIN criteria or use a INNER JOIN syntax instead.
Use like this
SELECT *
FROM GA
LEFT OUTER JOIN MOZ ON GA.Page = MOZ.URL
LEFT OUTER JOIN SF ON GA.Page = SF.Address
You don't include what your joining in the FROM clause also
SELECT *
FROM GA g
LEFT OUTER JOIN MOZ m ON g.Page = m.URL
LEFT OUTER JOIN SF s ON g.Page = s.Address

Trying to understand NULL operator in Query

I'm looking to see a breakdown of the total dollar business that each vendor has done (indirectly via the distributor) with each customer, where I'm trying not to use the Inner Join Syntax. I basically don't understand the difference between the two outputs produced by the two queries shown below:
Query1
select customers.cust_id, vendors.vend_id, sum(OrderItems.item_price*OrderItems.quantity) as total_business from
(((Vendors left outer join products
on vendors.vend_id = products.prod_id)
left outer join OrderItems
on products.prod_id = OrderItems.prod_id)
left outer join Orders
on OrderItems.order_num = Orders.order_num)
left outer join Customers
on Orders.cust_id = Customers.cust_id
group by Customers.cust_id, vendors.vend_id
order by total_business
I get the following output:
Query2
select customers.cust_id, Vendors.vend_id, sum(quantity*item_price) as total_business from
(((Vendors left outer join Products
on Products.vend_id = Vendors.vend_id)
left outer join OrderItems --No inner joins allowed
on OrderItems.prod_id = Products.prod_id)
left outer join Orders
on Orders.order_num = OrderItems.order_num)
left outer join Customers
on Customers.cust_id = Orders.cust_id
where Customers.cust_id is not null -- THE ONLY DIFFERENCE BETWEEN QUERY1 AND QUERY2
group by Customers.cust_id, Vendors.vend_id
order by total_business
I don't understand how there are only NULL cust_id's associated with the 1st Output when in the 2nd Output we get some non-NULL cust_ids. Why doesn't the 1st Output include these non-NULL cust_id's
Thank You
Query One is joining Vendors and Products incorrectly:
on vendors.vend_id = products.prod_id -- Vend_ID = Prod_ID
Query Two is joining Vendors and Products correctly:
on Products.vend_id = Vendors.vend_id -- Vend_ID = Vend_ID
Once that is fixed, you'll get the same IDs in both queries. Then I suggest you read Dan's answer to understand why what you were trying to do in eliminating INNER JOIN from the query is cancelled out by adding a WHERE filter to a column from the last table in the chain.
When you left join to a table, then filter on that table in the where clause, the join effectively changes to an inner join. The workaround is to apply the filter as a joining condition.
In your second query, all you have to do is is change the word "where" to "and".

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.

sql - How can I extract all information through one statement from 3 tables?

I have 3 tables.
First one:
Stores(StoreID, Name)
Second one:
Store_Items(StoreID, ItemID)
Third one:
Items(ItemID, Name, Price)
How can I write a single statement, which get all StoreID and all names and all items for each StoreID?
Should I use Join or something?
select *
from Store as S
left outer join Store_Items as SI on SI.StoreID = S.StoreID
left outer join Items as I on I.ItemID = SI.ItemID
select s.storeid, s.name, si.itemid, i.name, i.price
from store s
left join store_item si on si.storeid = s.storeid
left join item i on i.itemid = store.itemid
Yes, you should join the tables roughly as such
SELECT * FROM `firstone`
LEFT OUTER JOIN `secondone`
ON firstone.StoreId = secondone.StoreID
LEFT OUTER JOIN `thirdone`
ON secondone.ItemID = thirdone.ItemID

What kind of SQL join would this be?

I need to go to two tables to get the appropriate info
exp_member_groups
-group_id
-group_title
exp_members
-member_id
-group_id
I have the appropriate member_id
So I need to check the members table, get the group_id, then go to the groups table and match up the group_id and get the group_title from that.
INNER JOIN:
SELECT exp_member_groups.group_title
FROM exp_members
INNER JOIN exp_member_groups ON exp_members.group_id = exp_member_groups.group_id
WHERE exp_members.member_id = #memberId
SELECT g.group_title
FROM exp_members m
JOIN exp_member_groups g ON m.group_id = g.group_id
WHERE m.member_id = #YourMemberId
If there is always a matching group, or you only want rows where it is, then it would be an INNER JOIN:
SELECT g.group_title
FROM exp_members m
INNER JOIN
exp_member_groups g
ON m.group_id = g.group_id
WHERE m.member_id = #member_id
If you want rows even where group_id doesn't match, then it is a LEFT JOIN - replace INNER JOIN with LEFT JOIN in the above.