How to us Group By in SQL with a JOIN - sql

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;

Related

How to get Odoo Inventory adjustment value through SQL

I am working on a custom stock valuation module and in one model I am trying to get adjustment value for a lot - product - warehouse wise of the previous day.
QUERY 1
SELECT COUNT(*)
FROM
(
SELECT stock_inventory.date AS stock_adjustment_date,
stock_move_line.lot_id,
stock_move_line.product_id,
SUM(stock_move_line.qty_done) total_stock_adjustment
FROM stock_move_line
LEFT JOIN stock_move ON stock_move_line.move_id = stock_move.id
LEFT JOIN stock_inventory ON stock_move.inventory_id = stock_inventory.id
WHERE stock_move.inventory_id IS NOT NULL
AND stock_move_line.location_id = 5
AND stock_move_line.location_dest_id = 13
AND stock_move_line.lot_id IS NOT NULL
GROUP BY stock_move_line.lot_id, stock_move_line.product_id, stock_inventory.date
ORDER BY total_stock_adjustment DESC
)
testTable;
QUERY 2
SELECT COUNT(*)
FROM
(
SELECT stock_inventory.date AS stock_adjustment_date,
stock_move_line.lot_id,
stock_move_line.product_id,
SUM(stock_move_line.qty_done) total_stock_adjustment
FROM stock_move_line
LEFT JOIN stock_move ON stock_move_line.move_id = stock_move.id
LEFT JOIN stock_inventory ON stock_move.inventory_id = stock_inventory.id
WHERE stock_move.inventory_id IS NOT NULL
AND stock_move_line.location_id = 13
AND stock_move_line.location_dest_id = 5
AND stock_move_line.lot_id IS NOT NULL
GROUP BY stock_move_line.lot_id, stock_move_line.product_id, stock_inventory.date
ORDER BY total_stock_adjustment DESC
)
testTable;
Why these both queries returning same count 14,849 ?
13 is the warehouse ID and 5 is the virtual location used for adjustment. What I am doing wrong here?

ORA-00904: "Q"."ITEM_NO": invalid identifier - Oracle SQL group by issue

I have this query to fetch item no's and their quantities filtered by a specific unit.
select q.item_no, sum(q.quantity) from item_unit_quantity q
where q.unit_no = 'PH00000096' group by q.item_no
Now I want to add price column which I get from another two tables
There is a condition, Price is always the maximum of the latest three GRN dates.
select max(price) from (select price from grn_item gi join grn g on gi.grn_no = g.grn_no
where gi.item_no = 'IT00001896' order by g.grn_date desc) where rownum <= 3
When I combined the queries as below,
select q.item_no, sum(q.quantity),
(select max(price) from (select price from grn_item gi join grn g on gi.grn_no = g.grn_no
where gi.item_no = q.item_no order by g.grn_date desc) where rownum <= 3) "PRICE"
from item_unit_quantity q where q.unit_no = 'PH00000096' group by q.item_no
I get
ORA-00904: "Q"."ITEM_NO": invalid identifier
But if I change the above as "gi.item_no = 'IT00001896'" I get
ITEM_NO | Sum(Quantity) | Price
--------------------------------------
IT00012824 | 14 | 3.68
IT00006345 | 494 | 3.68
IT00001896 | 5 | 3.68
I still want to display the Item no, Item quantity and price for each Item no in this query, how can I do this?
Your question is a bit hard to follow without sample data. However, subqueries with GROUP BY can be finicky. A simple solution is to move the subquery to the FROM clause:
select q.item_no, sum(q.quantity), max(max_price)
from item_unit_quantity q left join
(select gi.item_no, max(g.price) as max_price
from grn_item gi join
grn g
on gi.grn_no = g.grn_no
group by gi.item_no
) gi
on gi.item_no = q.item_no
where q.unit_no = 'PH00000096'
group by q.item_no

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

Calculating cumulative summation using SQL based on Product Number

I have wrote an SQL query which allocates products to a customer based on the quantity remaining for each product in stock.
I.e. If OurQty = 55 and there are 70 outstanding orders split between 5 customers (Customer 1 = 35, Customer 2 = 10, Customer 3 = 3, Customer 4 = 16, Customer 5 = 6) then my SQL query will allocate the reserved product quantity to each customer sequentially until OurQty = 0 or all of the outstanding orders have been fulfilled.
My SQL query:
WITH allocate
AS (SELECT rd.ponum AS PONum,
od.orderline AS OrderLine,
rd.partnum AS PartNum,
p.partdescription AS PartDescription,
od.ordernum AS OrderNum,
rd.ourqty AS OurQty,
od.number01 AS Reserved,
rd.ourqty - od.number01 AS NewOurQty,
c.custnum AS CustNum,
c.name AS Name,
( rd.ourqty - Sum(od.number01)
OVER (
ORDER BY od.ordernum) ) AS CumulativeSum
FROM dbo.rcvdtl AS rd WITH (nolock)
INNER JOIN dbo.part AS p WITH (nolock)
ON rd.partnum = p.partnum
INNER JOIN dbo.orderdtl AS od WITH (nolock)
ON rd.partnum = od.partnum
INNER JOIN dbo.orderhed AS oh WITH (nolock)
ON od.ordernum = oh.ordernum
INNER JOIN dbo.customer AS c WITH (nolock)
ON od.custnum = c.custnum
WHERE ( rd.ponum = 73 )
AND ( od.number01 > 0 )
AND ( od.openline = 1 ))
SELECT ponum,
orderline,
partnum,
partdescription,
ordernum,
ourqty,
reserved,
newourqty,
custnum,
name,
cumulativesum + reserved AS 'Left In Stock',
CASE
WHEN ( cumulativesum + reserved ) - reserved > 0 THEN reserved
ELSE ( CASE
WHEN ( cumulativesum + reserved ) > 0 THEN
( cumulativesum + reserved )
ELSE 0
END )
END AS Allocated
FROM allocate
This works fine when the 'PartNum' is specified as a parameter. The problem arises when I query the table without specifying the 'PartNum' since the table contains multiple 'PartNums' which affects the accuracy of the 'CumulativeSum' which is used to check if (OurQty < CumulativeSum) and as such prevent the allocation of stock which does not physically exist.
My original idea was to pass the database table the 'PartNum' as a parameter for a given 'PONum' iteratively and then merge the results into one dataset on my application. Unfortunately the program I am using which calls the SQL query cannot pass the 'PartNum' to the SQL query as a parameter.
Therefore, Is it possible to calculate the cumulative sum for each PartNum in the table using SQL?
I am using Microsoft SQL Server 2012

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