Joining tables on foreign key - sql

I have the following three tables:
Product
Purchase (contains ProductID as foreign key)
Sale (contain ProductID as foreign key as well)
I want to form query joining these 3 tables where my result is the product name, purchased, and sold.
Product Name - (from Products table)
Purchased - (Number of occurences in Purchase table according to ProductID)
Sold - (Number of occurences in Sale Table according to ProductID)
Can you please set me on the right track by giving me hints and I'll complete by myself?

I'm betting this will get deleted...but hopefully you see this before it does. The following is really helpful in understanding the differences in the SQL JOINS. . This answer or Kyle's answers is all you need to solve your question.
Source: INNER JOIN, LEFT/RIGHT OUTER JOIN

As far as a hint, you need to use a join of some sort (join fundamentals).
A possible answer is below:
Select p.ProductName, pu.Purchased, s.Sold
From Products p
INNER JOIN Purchase pu on p.ProductID = pu.ProductID
INNER JOIN Sale s on s.ProductID = p.ProductID

Related

SQL Server need to find suppliers who supply the most different products

I have two tables I need information from, Products and Suppliers. Both these tables have a SupplierID column I am trying to use to join them together to retrieve the right info.
The output I need is SupplierID and ContactName from the Suppliers table. The correct output should contain only two suppliers, so I attempted something like this, but ran into a conversion error converting nvarchar value to a data type int. I am not supposed to count how many products they supply but aggregate functions seem like the best method to me.
SELECT TOP 2 ContactName, COUNT(Products.SupplierID) AS Supply
FROM Products
LEFT JOIN Suppliers ON Suppliers.ContactName = Products.SupplierID
GROUP BY Products.SupplierID, Suppliers.ContactName
ORDER BY Supply;
I have tried many different queries but none will work. I am confused on how to join these tables without running into errors. All the products have a unique ProductID as well. The correct output should look something like this:
7 John Smith
12 John Sample
Both these tables have a SupplierID column I am trying to use to join them together to retrieve the right info
If so, you should be joining on that column accross tables.
Also, it is a good practice to use table aliases and prefix each column with the table it belongs to.
Another remark is that if you want suppliers that sell the most different products, then you want to order by descending count (not ascending).
Finally, if you want to left join, then you should start from the suppliers and then bring in the products, not the other way around.
Consider:
select top 2
s.SupplierID,
s.ContactName,
COUNT(*) as Supply
from Suppliers s
left join Products p on p.SupplierID = s.SupplierID
group by s.SupplierID, s.ContactName
order by Supply desc;
You're currently joining on two different fields:
on Suppliers.ContactName = Products.SupplierID
Presumably this should be as follows?
on Suppliers.SupplierID = Products.SupplierID

How do I show all records from one table for each semi-related record in another?

This problem is extremely difficult to explain and I did not even know how to title it correctly so I do apologise about that in advance.
I have a view of products which is as follows:
Product
ProductId
ProductName
In my database, I have a ratecard table and a ratecard product table. A ratecard may be titled "Tier 1 Customers" and the corresponding RatecardProduct records would be prices for products for that particular ratecard. It may only contain prices for a few products and not all of them.
Ratecard
RatecardId
RatecardName
RatecardProduct
RatecardProductId
RatecardId
ProductId
UnitPrice
The problem is that I need to create a view which displays all products for all ratecards. If the ratecard / product combination does not have a corresponding unit price in my ratecardproduct table, it should show NULL or 0.
Imagine I have 10 products and 4 ratecards; the view would contain 40 records, even if the RatecardProduct table was completely empty
The reason I need to do this is because I am populating a gridview on viewing a ratecard and I do not want to have to do a round trip for each row to ascertain if there is a corresponding price.
Thank you so much in advance.
Generate all the rows. Then use left join to bring in the data:
select p.*, r.*, coalesce(rp.unitprice, 0) as unitprice
from products p cross join
ratecards r left join
ratecardproduct rp
on rp.productid = p.productid and rp.ratecardid = r.ratecardid;
Or don't use coalesce() if you want NULL.

Ambiguous Column Name Even Though Column Name and Table are Declared?

I am trying to create a query based on trying to find a value in one column of a table based on the values of another column in another table. This is the code I have written so far,
SELECT OrderDetails.OrderDetailID FROM OrderDetails
INNER JOIN OrderDetails
ON Products.ProductID = OrderDetails.ProductID
WHERE Products.SupplierID="5";
By executing the code, I want to find the OrderDetailID of the row in the OrderID Table where the SupplierID in the Products table is 5. For example,
Highlighted Products Table
The SupplierID of "Queso Cabrales" is 5 and its ProductID is 11. This corresponds to the foreign key in the table OrderDetail of 11 and therefore I want the primary key of that row to be returned. In this case 1.
Highlighted OrderDetails Table
At the moment I get an "ambiguous column name" error in the first line even though I have declared both the table and the column name. Also, how am I meant to ask SQL to fetch the data regarding other tables. I know I am mean't to use "INNER JOIN" but how do I execute so the WHERE command can be used.
You have OrderDetails twice in the FROM clause but no Products. I think you mean:
SELECT od.OrderDetailID
FROM OrderDetails od INNER JOIN
Products p
ON p.ProductID = od.ProductID
WHERE p.SupplierID = 5;
Notes:
Table aliases make the query easier to write and read (the od and p).
Don't use delimiters around numeric constants. I assume that SupplierId is a number, so I removed the double quotes.
You are using two time the same column so you must resove the amvbiguity eg: this way (using two distinct alias od1, od2)
SELECT od1.OrderDetailID FROM OrderDetails od1
INNER JOIN OrderDetails as od2
ON Products.ProductID = od2.ProductID
WHERE Products.SupplierID="5";
One problem is that INNER JOIN was designed to generate duplicate columns in the result. This problem was solved in 1992 when the SQL standard introduced 'relational' join types that don't generate duplicate attributes:
SELECT OrderDetailID
FROM OrderDetails
NATURAL JOIN Products
WHERE SupplierID = 5;

find the record that holds the foreign key

Let's say I have two tables, Product and Sale, Sale holds a foreign key to Product, so it's a one-to-many relationship with Product as one and Sale as many. How to write sql to get the Product of a Sale?
JOIN the two tables:
SELECT
*
FROM Product AS p
INNER JOIN Sale AS s ON s.ProductId = p.ProductId
WHERE s.SaleId = ...
Then you can specify a WHERE clause to filter on the Sale table, and SELECT whatever columns you want to select from the two tables.
You probably might need to have a look at the different types of JOINs:
A Visual Explanation of SQL Joins.

SQL Syntax for Complex Scenario (Deals)

i have a complex query to be written but cannot figure it out
here are my tables
Sales --one row for each sale made in the system
SaleProducts --one row for each line in the invoice (similar to OrderDetails in NW)
Deals --a list of possible deals/offers that a sale may be entitled to
DealProducts --a list of quantities of products that must be purchased in order to get a deal
now im trying to make a query which will tell me for each sale which deals he may get
the relevant fields are:
Sales: SaleID (PK)
SaleProducts: SaleID (FK), ProductID (FK)
Deals: DealID (PK)
DealProducts: DealID(FK), ProductID(FK), Mandatories (int) for required qty
i believe that i should be able to use some sort of cross join or outer join, but it aint working
here is one sample (of about 30 things i tried)
SELECT DealProducts.DealID, DealProducts.ProductID, DealProducts.Mandatories,
viwSaleProductCount.SaleID, viwSaleProductCount.ProductCount
FROM DealProducts
LEFT OUTER JOIN viwSaleProductCount
ON DealProducts.ProductID = viwSaleProductCount.ProductID
GROUP BY DealProducts.DealID, DealProducts.ProductID, DealProducts.Mandatories,
viwSaleProductCount.SaleID, viwSaleProductCount.ProductCount
The problem is that it doesn't show any product deals that are not fulfilled (probably because of the ProductID join). i need that also sales that don't have the requirements show up, then I can filter out any SaleID that exists in this query where AmountBought < Mandatories etc
Thank you for your help
I'm not sure how well I follow your question (where does viwSaleProductCount fit in?) but it sounds like you will want an outer join to a subquery that returns a list of deals along with their associated products. I think it would go something like this:
Select *
From Sales s Inner Join SaleProducts sp on s.SaleID = sp.SaleID
Left Join (
Select *
From Deals d Inner Join DealProducts dp on d.DealID = dp.DealId
) as sub on sp.ProductID = sub.ProductID
You may need to add logic to ensure that deals don't appear twice, and of course replace * with the specific column names you'd need in all cases.
edit: if you don't actually need any information from the sale or deal tables, something like this could be used:
Select sp.SaleID, sp.ProductID, sp.ProductCount, dp.DealID, dp.Mandatories
From SaleProducts sp
Left Join DealProducts as dp on sp.ProductID = dp.ProductID
If you need to do grouping/aggregation on this result you will need to be careful to ensure that deals aren't counted multiple times for a given sale (Count Distinct may be appropriate, depending on your grouping). Because it is a Left Join, you don't need to worry about excluding sales that don't have a match in DealProducts.