Stock balance from items in Boms - sql

I have Bom table like
ItemCode MatCode Quantity
032490 M10506 3.0
032490 M10507 1.0
032490 M10509 1.0
030515 M10506 2.0
030515 M10508 5.0
045660 M10507 2.0
045660 M10510 3.0
Stock balance is known for assembled items in Item table.
ItemCode StockBalance
032490 10
030515 15
045660 8
M10506
M10507
M10508
M10509
M10510
I need to calculate balance for all materials (MatCode) in Stock as part of assembled products. So in my example for M10506 it would be 10*3+15*2.
I'm stuck with this, looping the query and right now there's only 1 level boms but in future there will be 2 and 3 level boms.
My query:
Select sum(item.StockBalance * bom.Quantity) from item
inner join bom on bom.ItemCode=item.itemcode
Where exists (select * from bom WHERE Item.itemCode = bom.ItemCode)
Group by bom.ItemCode

Your data suggests a join and aggregation:
select b.matCode, sum(b.quantity * i.StockBalance)
from bom b join
item i
on b.itemCode = i.itemCode
group by b.matCode;

Related

How to us Group By in SQL with a JOIN

I am wondering if anyone could help me. I trying to write a query which will group all the order detail lines to each product.
SELECT
Line.NetAmount, Line.QtyDespatch, Line.QtyOrder,
Line.Price, Line.Price * Line.QtySent AS 'Value'
FROM dbo.orderdetails line
LEFT JOIN
(
SELECT products.ProductID, products.CompanyID AS StockCompanyID,
products.StockCode FROM dbo.products
)
Stock ON Line.ProductID = products.ProductID AND products.StockCompanyID = Line.CompanyID
WHERE Line.CompanyID = 1
ORDER BY Stock.StockID ASC
The results I am getting are for each order details line individually but I want to group-by the each product id and have (Line.Price * Line.QtySent) as sum for each product and show each product once.
The result I am getting are
PID Net sent qty Price Value
39044 12 0 5 2.4 0
39044 12 0 5 2.4 0
39044 12 0 5 2.4 0
39044 12 0 5 2.4 0
But I do not want to get it for each line but a cumulative value for all line by product. Basically cumulative totals for each product
You would need to group by the ProductId and then sum the Line.Price multiplied by the Line.QtySent. You would want something like this:
SELECT p.ProductID, SUM(Line.Price * Line.QtySent) AS 'Value'
FROM dbo.orderdetails line
LEFT JOIN dbo.products p ON
Line.ProductID = p.ProductID AND p.CompanyID = Line.CompanyID
WHERE Line.CompanyID = 1
GROUP BY p.ProductID
Your description sounds like this query:
SELECT od.ProductId, SUM(od.Price * od.QtySent) as total
FROM dbo.orderdetails od
GROUP BY od.ProductId;

SQL Using Multiply 3 Times with different ID's

I have tables called Products and ProductsDetails. I want to get something like the price of an order. So let's say I want 5 pairs of "Headphonesv1" ( Comparing with not ID but name, since name could change ), 2 packs of "GumOrbit" and 7 packs of "crisps". Pair of headphonesv1 costs 10$, gum 1$ and crisps 2$. So the answer that I should get is bill ID, Bill date, and TotalCost which is = 66. My question is how do I make multiple calculations? The code that I've been trying with one at least but I get syntax error:
SELECT Products.billID, Products.Date, (ProductsDetails.Price * 5 WHERE ProductsDetails.name LIKE 'Headphonesv1')
FROM Products INNER JOIN ProductsDetails ON Products.billdID = ProductsDetails.billID
Also have tried inserting SELECT inside () but then the values that I get are wrong and creating one more inner join inside doesn't seem promising
I think if you just want to see that total cost for multiple items you can use a aggregate and case expression to get the SUM.
SELECT Products.billID,
Products.Date,
SUM(CASE WHEN ProductsDetails.name LIKE 'Headphonesv1' THEN ProductsDetails.Price * 5
WHEN ProductsDetails.name LIKE 'GumOrbit' THEN ProductsDetails.Price * 2
WHEN ProductsDetails.name LIKE 'crisps' THEN ProductsDetails.Price * 7
END) TotalCost
FROM Products
INNER JOIN ProductsDetails ON Products.billdID = ProductsDetails.billID
GROUP BY Products.billID,
Products.Date
this seems very hard coded to serve much use though
Your previous code has a few synax erros. you are closing your parenthesis in the wrong location, and the FROM ... clause should be before the WHERE ... clause. Change your code to this:
SELECT Products.billID, Products.Date, (ProductsDetails.Price * 5)
FROM Products INNER JOIN ProductsDetails ON Products.billdID = ProductsDetails.billID
WHERE ProductsDetails.name LIKE 'Headphonesv1'
and let me know if it works now.
Edited:
The OP requested how to obtain that information for more than one Product. In that case you could switch the statement to:
SELECT SUM(Cost)
FROM (
SELECT Products.billID, Products.Date,
(ProductsDetails.Price *
(CASE WHEN ProductsDetails.name='Headphonesv1' THEN 5 ELSE
CASE WHEN ProductsDetails.name='GumOrbit' THEN 7 ELSE 0 END
END)
) AS Cost
FROM Products INNER JOIN ProductsDetails ON Products.billdID = ProductsDetails.billID
WHERE (ProductsDetails.name = 'Headphonesv1') OR (ProductsDetails.name = 'GumOrbit')
)
And you can continue to add more products.
You probably have another two tables: cart(cartID int/*,more info*/) and cartItems(cartID int /*FK*/, item varchar(50),qty int) where you add something. Finally,
select sum(pd.price * ci.qty) tot
FROM Products p
INNER JOIN ProductsDetails pd ON p.billdID = pd.billID
inner join cartItems ci on ci.item = pd.name
inner join cart c on c.cartID = ci.cartID
where c.cartID = 123456

Sum of a subquery?

Background:
We are doing a price adjustment in our database. The price adjustment is based on the bill of materials, and what each materials' new cost is. So I have to select the item from the item table, its BOM, and the new price table, and adjust the price based on the total of the materials it takes to make each item. Items are comprised of varying quantities of varying materials, so the master query will call this subquery to get the total adjustment:
select
ta.Code,
ta.Quantity,
(select tb.cost - tb.NewCost * ta.Quantity ) as BOMEffect
from BOM TA
inner join ITEM TC on tC.ItemCode = tA.Father
inner join NewPriceTable TB on tA.Code = tB.Item
where TA.Father = '100-01'
and tc.PriceList = 3
order by ta.Father
Which gives me the results (this is all of the materials of one item, quantity of each material, and the price adjustment):
Code Quantity BOMEffect
D .003 56.000000 -95.08
D .004 28.000000 -62
D .005 20.000000 -54.6
d .006 2.000000 -3.3
D .01 2.000000 -5.5
D .015 4.000000 -25.52
D .02 4.000000 -34
All I need from this query is the total BOMEffect (-280). But if I just replace the select statement with:
select
sum((select tb.cost - tb.NewCost * ta.Quantity )) as BOMEffect
from BOM TA
inner join ITEM TC on tC.ItemCode = tA.Father
inner join NewPriceTable TB on tA.Code = tB.Item
where TA.Father = '100-01'
and tc.PriceList = 3
order by ta.Father
I get:
Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
I know what it's saying, but I don't know any other way to do it. How else can I get this total? This is a small subquery that is part of a larger query, so I only need to return the total. I could probably use a view or a temp table, but I would like to stay away from that if possible.
remove the select inside the sum and order by
select
sum(tb.cost - tb.NewCost * ta.Quantity) as BOMEffect
from BOM TA
inner join ITEM TC on tC.ItemCode = tA.Father
inner join NewPriceTable TB on tA.Code = tB.Item
where TA.Father = '100-01'
and tc.PriceList = 3
If you want to include Code and Quantity you would have to include those in the GROUP BY clause:
select
ta.Code,
ta.Quantity,
sum(tb.cost - tb.NewCost * ta.Quantity) as BOMEffect
from BOM TA
inner join ITEM TC on tC.ItemCode = tA.Father
inner join NewPriceTable TB on tA.Code = tB.Item
where TA.Father = '100-01'
and tc.PriceList = 3
GROUP BY ta.Code, ta.Quantity

How to SUM an AS column in SQL

I have the following code...
SELECT WF.Word, WF.Frequency, WW.Weight, (WF.Frequency * WW.Weight) AS Product
FROM WF
INNER JOIN WW ON WW.Word = WF.word
Which outputs the following...
WORD | FREQUENCY | WEIGHT | PRODUCT
Fat 3 2 6
Ugly 2 4 8
Stupid 1 7 7
I also want to sum the product column at the same time. I understand how to sum an existing column but unsure how to sum a column i'm creating.
SELECT SUM(WF.Frequency * WW.Weight) AS Product
FROM WF
INNER JOIN WW ON WW.Word = WF.word
SELECT WF.Word, SUM(WF.Frequency) Frequency, SUM(WW.Weight) Weight, SUM(WF.Frequency * WW.Weight) AS Product
FROM WF
INNER JOIN WW ON WW.Word = WF.word
GROUP BY WF.Word
;
SELECT SUM(WF.Frequency * WW.Weight) Product
FROM WF
INNER JOIN
WW ON WW.Word = WF.word

Trying to Calculate Qty on Hand and Value on hand with multiple shipments

I have this query, I have an Acquisitions table (Incoming) and Invoice Table (Outgoing) I am trying to calculate the Value on Hand by taking the AVG dbo.tblAcqDetail.AcqPrice * the QtyOnHand which is figured taking Incoming - Outgoing. When I add a line item on the Acquisitions table that has a different cost for the same item, the AVG is not grouping and showing instead two line items example below. The shipment side works fine with multiple line items...
Product QtyIn QtyOut On_Hand AVGPrice Value_OnHand
Screws 100 30 70 25.0000 1750.0000
Nuts 50 10 40 40.0000 1600.0000
Nuts 100 10 90 50.0000 4500.0000
Bolts 100 20 80 100.000 8000.0000
.
SELECT DISTINCT
dbo.tblProduct.Product ,
SUM(DISTINCT dbo.tblAcqDetail.AcqQuantity) AS QtyIN ,
SUM(DISTINCT dbo.tblInvoiceDetail.InvQuantity) AS QtyOut ,
SUM(DISTINCT dbo.tblAcqDetail.AcqQuantity)
- SUM(DISTINCT dbo.tblInvoiceDetail.InvQuantity) AS On_Hand ,
dbo.tblAcqDetail.AcqPrice ,
dbo.tblAcqDetail.AcqPrice
* ( SUM(DISTINCT dbo.tblAcqDetail.AcqQuantity)
- SUM(DISTINCT dbo.tblInvoiceDetail.InvQuantity) ) AS Value_Hand
FROM dbo.tblAcq
INNER JOIN dbo.tblAcqDetail ON dbo.tblAcq.acqID = dbo.tblAcqDetail.AcqID
INNER JOIN dbo.tblProduct ON dbo.tblAcqDetail.ProductID = dbo.tblProduct.ProductID
INNER JOIN dbo.tblInvoiceDetail ON dbo.tblProduct.ProductID = dbo.tblInvoiceDetail.ProductID
INNER JOIN dbo.tblInvoice ON dbo.tblInvoiceDetail.InvoiceID = dbo.tblInvoice.InvoiceID
GROUP BY dbo.tblProduct.Product ,
dbo.tblAcqDetail.AcqPrice
Basing on PinnyM's answer, you don't need DISTINCT, I re-write your query as following using table alias:
SELECT
P.Product ,
SUM( AcD.AcqQuantity) AS QtyIN ,
SUM( InD.InvQuantity) AS QtyOut ,
SUM( AcD.AcqQuantity)
- SUM( InD.InvQuantity) AS On_Hand ,
AcD.AcqPrice ,
AcD.AcqPrice
* ( SUM(AcD.AcqQuantity)
- SUM( InD.InvQuantity) ) AS Value_Hand
FROM dbo.tblAcq Ac
INNER JOIN dbo.tblAcqDetail AcD ON Ac.acqID = AcD.AcqID
INNER JOIN dbo.tblProduct P ON AcD.ProductID = P.ProductID
INNER JOIN dbo.tblInvoiceDetail InD ON P.ProductID = InD.ProductID
INNER JOIN dbo.tblInvoice Inv ON InD.InvoiceID = Inv.InvoiceID
GROUP BY P.Product ,
AcD.AcqPrice
By reading this query, I don't understand why you need table dbo.tblInvoice, it is not part of aggregation.
The reason you still see different product is because you group by two columns P.Product, AcD.AcqPrice, not only Product, in your return result you can see their combination is unique.
To be mathematically accurate, you should not be using SUM(DISTINCT fieldname), but just SUM(fieldname). Otherwise, it will eliminate entries that happen to have the same quantity.
For that matter, you shouldn't be using DISTINCT at the beginning of your query either, GROUP BY already handles that.
If you believe you have duplicate rows being returned by your JOINs (which you shouldn't really if you're doing it right), wrap them in a subquery using DISTINCT before trying to aggregate.
As an example, a subquery to eliminate duplicates can be written like so:
SELECT
Product ,
SUM(AcqQuantity) AS QtyIN ,
SUM(InvQuantity) AS QtyOut ,
SUM(AcqQuantity)
- SUM(InvQuantity) AS On_Hand ,
AcqPrice ,
AcqPrice
* ( SUM(AcqQuantity)
- SUM(InvQuantity) ) AS Value_Hand
FROM (SELECT DISTINCT
dbo.tblProduct.Product ,
dbo.tblAcqDetail.AcqQuantity,
dbo.tblInvoiceDetail.InvQuantity,
dbo.tblAcqDetail.AcqPrice
FROM
dbo.tblAcqDetail
INNER JOIN dbo.tblProduct ON dbo.tblAcqDetail.ProductID = dbo.tblProduct.ProductID
INNER JOIN dbo.tblInvoiceDetail ON dbo.tblProduct.ProductID = dbo.tblInvoiceDetail.ProductID
INNER JOIN dbo.tblInvoice ON dbo.tblInvoiceDetail.InvoiceID = dbo.tblInvoice.InvoiceID ) productInfo
GROUP BY Product, AcqPrice