Selecting data from 3 tables to calculate inventory levels - sql

I am currently setting up an inventory system in phpgrid. I have 3 tables - products, orders, purchases. I am trying to list all of the PartNumber field from products and the total of the NumberReceived for each PartNumber from purchases along with the total of the NumberShipped for each PartNumber from orders.
From there I believe I can use phpgrid to display a virtual/calculated column that will subtract the NumberShipped from the NumberReceived and give me the current stock level of each PartNumber.
Looking for results something like this:
PartNumber | Received | Shipped | (calculated) Qty On Hand
______________________________________________________________
12345 | 20 | 10 | 10
67890 | 40 | 5 | 35
I am having trouble wrapping my head around how to join everything together to retrieve the data that I want. This SELECT displays some data but not every PartNumber with the proper calculations.
"SELECT
p.id,
sum(p.NumberReceived) AS 'Received',
sum(o.NumberShipped) As 'Shipped'
FROM purchases p
INNER JOIN orders o on p.id = o.ProductId
GROUP BY p.id ",
"id", "purchases");
I realized that I need to have the PartNumber column in there in order to list all the data of the PartNumber field. So then I tried this - I think I'm close but this keeps giving me an error - PHPGRID_ERROR: Could not execute query. Error 102
"SELECT
prod.id,prod.PartNumber,
sum(pur.NumberReceived) AS 'Received',
sum(o.NumberShipped) As 'Shipped',
FROM products prod
LEFT JOIN orders o ON prod.PartNumber = o.ProductId
LEFT JOIN purchases pur ON prod.PartNumber = pur.ProductId",
"id", "products");
I'm hoping someone could help steer me in the right direction. Thank you all!

If you are summing you need to group by. The following should work. If not, send specific error message.
(you also had an extra comma after the last item in the select block)
SELECT
prod.id,prod.PartNumber,
sum(pur.NumberReceived) AS Received,
sum(o.NumberShipped) As Shipped
FROM products prod
LEFT JOIN orders o ON prod.PartNumber = o.ProductId
LEFT JOIN purchases pur ON prod.PartNumber = pur.ProductId"
GROUP BY prod.id, prod.PartNumber;

Related

Access 2002 SQL for joining three tables

I have been trying to get this to work for a while now. I have 3 tables. First table has the Sales for customers which include the CustomerID, DateOfSales (Which always has the first of the month). The second table has the CustomerName, CustomerID. The third table has which customers buy what product lines. They are stored by CustomerID, ProductID.
I want to get a list (from one SQL hopefully) that has ALL the customers that are listed as buying a certain ProductID AND the maxDate from the Sales. I can get all of them IF there are sales for that customer. How the heck do I get ALL customers that buy the certain ProductID AND the maxDate from Sales or NULL if there is no sales found?
SalesList |CustomerList|WhoBuysWhat
----------|------------|-----------
maxDate |CustomerID |CustomerID
CustomerID| |ProductID=17
This is as close as I got. It gets all max dates but only if there have been sales. I want the CustomerID and a NULL for the maxDate if there were no sales recorded yet.
SELECT WhoBuysWhat.CustomerID, CustomerList.CustomerName,
Max(SalesList.MonthYear) AS MaxOfMonthYear FROM (CustomerList INNER
JOIN SalesList ON CustomerList.CustomerID = SalesList.CustomerID) INNER
JOIN WhoBuysWhat ON CustomerList.CustomerID = WhoBuysWhat.CustomerID
WHERE (((SalesList.ProductID)=17)) GROUP BY WhoBuysWhat.CustomerID,
CustomerList.CustomerName;
Is it possible or do I need to use multiple SQL statements? I know we should get something newer than Access 2002 but that is what they have.
You want LEFT JOINs:
SELECT cl.CustomerID, cl.CustomerName,
Max(sl.MonthYear) AS MaxOfMonthYear
FROM (CustomerList as cl LEFT JOIN
(SELECT sl.*
FROM SalesList sl
WHERE sl.ProductID = 17
) as sl
ON cl.CustomerID = sl.CustomerID
) LEFT JOIN
WhoBuysWhat wbw
ON cl.CustomerID = wbw.CustomerID
GROUP BY cl.CustomerID, cl.CustomerName;

compare two tables using full outer join to highlight missing record from table

I have two tables.
The first table, tblBasket is shown below,
Code ProductCode Price
SLK ABC 20
SLK DEF 30
SLK GHI 40
The second table, tblOrders is shown below,
Code ProductCode SaleId Amount
SLK ABC MMM 20
SLK DEF MMM 30
SLK GHI MMM 40
SLK ABC XXX 20
SLK DEF XXX 30
I need to check the tblBasket against tblOrders. The logic is that the basket is sold as a whole i.e. all 3 products with the code SLK must be sold together.
In the table tblOrder is a list of orders from different sales people (SaleId). Each SaleId where it has the code SLK should have the same 3 product codes as the basket. So in the above example saleId XXX is missing the product GHI. I need a query to flag this.
I tried the query below but it only return me 5 records it doesn't show me the missing product from saleId XXX even though I'm using a full outer join.
select * from tblBasket b full outer join tblOrders o
on b.Code = o.Code and b.ProductCode = o.ProductCode
You can summarize the data to get the number of expected and matching products for each sale. Assuming that there are no duplicates in either table:
select sc.saleid, sc.code,
count(*) as numProducts,
count(o.productcode) as numMatchingProducts
from (select distinct saleid, code from tblOrders o) sc join
tblBasket b
on b.code = sc.code left join
tblOrders o
on o.saleid = sc.saleid and o.code = sc.code and
b.productcode = o.productcode
group by sc.saleid, sc.code;
The logic is to generate the full combination of all products for each saleid. Then, the left join determines whether or not the products in the order match the expected products.
You can then add a having clause if you want to get some subset of orders -- such as the complete ones, or the incomplete ones, or the ones missing one product.
Do a left outer join from tblOrders to tblBaskets, joining on ProductCode. If you just want the orders where its missing a product, simply add a "WHERE tblBaskets.ID IS NULL"

How do I query this case?

I have three tables.
Category(id, name);
Item(id, name, category);
SoldItem(id, item, qty);
My goal is simple, I want to list ALL the categories plus item count of those categories plus the count of sold items of the items of those particular categories as rows.
The result would be like this:
Category | Item count | Item sold count
----------------------------------------
Food | 2 | 50
----------------------------------------
Beverage | 3 | 60
How do I query this in PostgreSQL. Thanks in advance.
The key is to use count(distinct) when counting rows from the middle joined table, otherwise multiple grandchildren would result in the same patent being counted multiple times too:
select
c.name as category,
count(distinct i.id) as item_count,
sum(si.qty) as item_sold_count
from Category c
left join Item i on i.category = c.id
left join SoldItem si on si.item = i.id
group by c.name;
By using left joins, categories without items, and items with sales, will still show but with zeros for the totals.

SQL Select statement which shows row-specific count information?

I need some SQL help ..
Suppose I have 2 tables: Customers and Products.
Now, I want to see a SQL statement that will show me these two columns:
Customer | Number of orders placed
How do I do that ?
The second column is a non-existent column, which is showing a number which states how many orders that customer has placed.
For example:
Customer | Number of orders placed
-------- | -----------------------
John | 23
Jack | 5
Mary | 12
etc ..
What's the SQL for this kind of a select ?
I guess that the Product table contains a foreign key CustomerID which references the Customer. The resulting query would be
select Customers.Name, Count(*)
from Customers join Products
on Customers.CustomerID = Products.CustomerID
However, this is just a guess as you forgot to inform us about the relation between the two tables, i.e. how the Products know to which Customer they belong.
Also, but this is a bit picky, you want the number of orders but only have a 'Product' table...
JOIN. This is just making up your column names since tables weren't given.
SELECT
c.Name,
myOrders = COUNT(o.id)
FROM Customers c
INNER JOIN Orders o
ON c.id = o.customerId
GROUP BY c.Name
Some quick reading: JOINS. GROUP BY

Pervasive Sql 10 Join one table, onto another, onto another

I have a table with products.
When I get information from that table, I would also like to get the ETA of that article. To do so, I am planning to get the latest purchase Order Row, that is on this article, and then get the expected delivery of this purchase.
This is three different tables and I would like it to be like another column on the query, so I can get the value from the column like I would if it was on the same table.
Is my idea possible? If there is no purchase order on this article I would like the value to be null.
Products
Int ProductId
Int Price
Sample data
ProductId Price
-----------------
1 100
2 300
PORows
Int RowId
Int ProductId
Int POId
Sample data
RowId ProductId POId
-----------------------
1 1 1
PO
Int POId
DateTime ETA
Sample data
POId ETA
-----------------------
1 2010-10-25 10:05
So the result I would want is:
ProductId Price ETA (null if no rows exist)
------------------------------------------------
1 100 2010-10-25 10:05
2 300 NULL
Use:
SELECT p.productid,
p.price,
x.max_eta
FROM PRODUCTS p
LEFT JOIN POROWS r ON r.productid = p.productid
LEFT JOIN (SELECT po.id,
MAX(po.eta) AS max_eta
FROM PO po
GROUP BY po.id) x ON x.poid = r.poid
Pervasive is the only database I'm aware of that won't allow you to omit the INNER and OUTER keywords. v10 might've relaxed that, but I know it's the case for v8 and 2000.
I don't know Pervasive but in SQL standard you can make the select for the latest PO an aliased subquery
select Products.id, products.name, ProductETAS.ETA
from Products
left join
(
select POLINES.productid, min(PO.ETA) as ETA from PO inner join POLINES
on PO.id = POLINES.POid and POLINES.productid = ?
where PO.ETA >= today
group by POLINES.productid
) as ProductETAS
on Products.productid = ProductETAS.productid