Calculate column amount and get total with order number? - sql

How to calculate each order number amount and total amount with SQL status
Order_no Status Amount
9008258656 P 50.00
9008258656 P 0.00
9008510713 P 50.00
9008510713 P 0.00

Well, it looks like you want a simple aggregated query :
SELECT order_no, count(*) number_of_orders, sum(amount) total_amount
FROM orders
GROUP BY order_no
If you need to filter on a specific status :
SELECT order_no, count(*) number_of_orders, sum(amount) total_amount
FROM orders
WHERE status = 'P'
GROUP BY order_no

If you are looking to keep your individual line numbers (i.e. 4 total records) and not have aggregates (i.e. 2 total records), you can use the sum window function.
SELECT ord.Order_no
, ord.Status
, ord.Amount
, TotalSum = SUM(ord.Amount)OVER(PARTITION BY ord.Order_no, ord.Status)
FROM Orders ord
This would produce the following result:
Order_no Status Amount TotalAmount
9008258656 P 50.00 50.00
9008258656 P 0.00 50.00
9008510713 P 50.00 50.00
9008510713 P 0.00 50.00
Based off the example you provided, there probably is not much value in doing the sum over in this scenario. #GMB's response should suffice. However, there are a lot of cool things you can do with the sum window function such as running totals. For example, if you had an order date column, you can include after the PARTITION BY ord.Order_no, ord.Status ORDER BY ord.Order_date and this would give you a running sum of the amount that increments by each order. I.E:
Order_no Order_date Status Amount RunningTotal
9008258656 1/2/2019 P 50.00 50.00
9008258656 1/3/2019 P 0.00 50.00
9008258656 1/4/2019 P 50.00 100.00
9008258656 1/5/2019 P 0.00 100.00

Related

Find the products contributing to the 50% of the total sales using SQL SUM window Function

There are two Tables - orders and item_line
orders
order_id
created_at
total_amount
123
2022-11-11 13:40:50
450.00
124
2022-10-30 00:40:50
1500.00
item_line
order_id
product_id
product_name
quantity
unit_price
123
a1b
milo
4
100.00
123
c2d
coke
5
10.00
124
c2d
coke
150
10.00
The question is:
Find the products contributing to the 50% of the total sales.
My take on this is -
SELECT i.product_name,SUM(o.total_amount)AS 'Net Sales'
FROM item_line i
JOIN orders o on o.order_id = i.order_id
GROUP BY i.product_name
HAVING SUM(o.total_amount) = (SUM(o.total_amount)*0.5);
But this is not correct. SUM windows functions need to be used, but how?
Try the following, explanation is within the query comments:
-- find the the total sales for each product
WITH product_sales AS
(
SELECT product_id, product_name,
SUM(quantity * unit_price) AS product_tot_sales
FROM item_line
GROUP BY product_id, product_name
),
-- find the running sales percentage for each product starting from porduct with highest sales value
running_percentage AS
(
SELECT product_id, product_name, product_tot_sales,
SUM(product_tot_sales) OVER (ORDER BY product_tot_sales DESC) /
SUM(product_tot_sales) OVER () AS running_sales_percentage,
SUM(product_tot_sales) OVER () AS tot_sales
FROM product_sales
)
-- select products that have a running sales percentage less than the min(running_sales_percentage) where running_sales_percentage >= 0.5
-- this will select all of products that contributes of 0.5 of the total sales
SELECT product_id, product_name, product_tot_sales,
tot_sales,
running_sales_percentage
FROM running_percentage
WHERE running_sales_percentage <=
(
SELECT MIN(running_sales_percentage)
FROM running_percentage
WHERE running_sales_percentage >= 0.5
)
You don't need a join with orders table, all data you need is existed in the item_line table.
See demo.

Discount Present Update When Quantity Change

I have table call tblInvoice. This is my table with some data.
InvoiceNo
ItemName
Quantity
CostPrice
ItemCode
DiscountPrice
DisPresent
Amount
GrossAmount
SalePrice
INV01
80= BK
10
30.00
EX80=
40.00
100.00
400.00
575.00
50.00
INV01
80= BK
5
30.00
EX80=
35.00
75.00
175.00
575.00
50.00
My client is sell same item with different price. as you can see here DiscountPrice is different but ItemName and ItemCode is same. When return product after sold I want to subtraction quantity. Its ok I already done that part. But problem is I want to update DiscountPesent after return product. its like this. Imagine I return 1 Book DiscountPrice is 40.00. Not 35.00. I want to update only first row. not both rows. I want to get DiscountPresent Like this.
SalePrice - DiscountPrice * Quantity = DiscountPresent
According to the above table. Imagine I subtraction 1 Quantity from DiscountPrice 40.00 row. now My Quantity is 9 I want to get DiscountPresent Like this.
50 - 40 = 10 * 9 = 90
I used following query for achieve this. sometimes its work as expected. but sometimes DiscoutPresent Switching with second row DiscountPeresent. After that table look like this.
InvoiceNo
ItemName
Quantity
CostPrice
ItemCode
DiscountPrice
DisPresent
Amount
GrossAmount
SalePrice
INV01
80= BK
9
30.00
EX80=
40.00
75.00
400.00
575.00
50.00
INV01
80= BK
5
30.00
EX80=
35.00
90.00
175.00
575.00
50.00
90 is come to second row. 75 is come to first row. its wrong. I used following code. sometimes its work as expected. but sometimes it switching DiscountPresent.
UPDATE ps
SET DisPresent = ((i.SalePrice) - (i.DiscountPrice)) * (i.Quantity)
FROM tblInvoice ps JOIN
(SELECT i.InvoiceNo, i.DiscountPrice, i.Quantity, i.SalePrice FROM tblInvoice i
GROUP BY i.DiscountPrice, i.InvoiceNo, i.Quantity, i.SalePrice)i
ON ps.InvoiceNo = i.InvoiceNo
looks to me you only need a simple update statement
UPDATE i
SET DisPresent = (i.SalePrice - i.DiscountPrice) * i.Quantity
FROM tblInvoice i
if this is not what you wanted, please show the expected result for the sample data that you have provided
if you are returning any product you should update only that invoice
UPDATE ps
SET DisPresent = ((i.SalePrice) - (i.DiscountPrice)) * (i.Quantity)
FROM tblInvoice where invoiceid=1 and itemcode='EX80='

Applying percent change based on unique identifier

I'm calculating margins from a sales table in SQL and I need to reduce sales amounts if there is a discount in a sale based on it's invoice number. For this sample a 25% discount is applied Invoice 123. The total sales amount for invoice 123 is $100.00 but there is a 25% discount applied to that amount. What I want to do is apply that 25% discount to all sales numbers for invoice 123 so I can get the actual revenue number.
Sample Data:
ID Type ProductType Amount
123 Sale Jeans 50.00
123 Sale T-Shirt 30.00
123 Sale Sock 20.00
123 Discount - 25% NULL -25.00
456 Sale Jeans 60.00
456 Sale T-Shirt 40.00
456 Sale Sock 70.00
Expected Result:
ID Type ProductType Amount Actual Amount
123 Sale Jeans 50.00 41.67
123 Sale T-Shirt 30.00 21.67
123 Sale Sock 20.00 11.67
123 Discount - 25% NULL -25.00 0.00
456 Sale Jeans 60.00 60.00
456 Sale T-Shirt 40.00 40.00
456 Sale Sock 70.00 70.00
I've tried creating a new column where I multiple the amount times the discount rate but I can't get the numbers correct because it needs to be applied to the invoice number each discount corresponds to.
I'd like to have a new column that shows the adjusted amount based on the discount rate and then the discount amount showing zero.
One way is to use window functions to calculate the sum of the negative values for an id divided by the number of non negative values for that id by CASE expressions as arguments to the functions. The result of the division can than be deducted from the price. Additionally use a CASE to get zero for the negative values.
SELECT t1.id,
t1.amount,
CASE
WHEN t1.amount <= 0 THEN
0
ELSE t1.amount
+ sum(CASE
WHEN t1.amount < 0 THEN
t1.amount
ELSE
0
END) OVER (PARTITION BY t1.id)
/
count(CASE
WHEN t1.amount >= 0 THEN
1
END) OVER (PARTITION BY t1.id)
END actual_amount
FROM elbat t1;
db<>fiddle

JOIN Multiple Tables with SUM

I need help with the scenario below.
order table
orderId orderAmount
10001 1000.00
10002 2000.00
10003 3000.00
10004 1000.00
10005 1000.00
transfer table
transferId orderId transferAmount
9001 10001 100.00
9002 10001 200.00
9003 10001 25.00
9004 10002 250.00
9005 10002 450.00
9006 10004 100.00
returns table
returnId orderId returnAmount
8001 10001 450.00
8002 10001 50.00
8003 10002 245.00
8004 10003 100.00
Result Needed
/*include all orders from orders table, even if no transfers or returns*/
orderId transfers returns
10001 325.00 500.00 /*sum of transfers and returns per orderId from respective tables*/
10002 700.00 245.00
10003 0.00 100.00
10004 100.00 0.00
10005 0.00 0.00 /*use zero whenever no rows for orderId in respective table*/
How can I implement the above in single query?
This is tricky. I think the easiest way is union all. If I have the arithmetic correct, you want to add the order amount to transfers but not returns:
select orderId,
sum(transfers) as transfers,
sum(returns) as returns
from ((select orderId, Amount, 0 as transfers, 0 as returns
from orders o
) union all
(select orderId, 0, transferAmount, 0
from transfers
) union all
(select orderId, 0, 0, returnAmount
from transfers
)
) otr
group by orderId;
You can just select all the order lines.
For each order, you subquery the tables linked by the OrderId.
SELECT o.orderId
, (SELECT sum(TransferAmount)
FROM Transaction t
WHERE t.OrderId = o.OrderId) 'Transaction'
, (SELECT sum(r.ReturnAmount)
FROM Result r
WHERE r.OrderId = o.OrderId) 'Return'
FROM Order o
I would use derived tables, something like (Apologies if the syntax is a little off, not tested):
SELECT O.OrderID,COALESCE(T.Total,0) AS [Transfer Total],COALESCE(R.Total,0) AS [Return Total]
FROM Orders AS O
LEFT JOIN
(
SELECT T.OrderID,SUM(T.TransferAmount) [Total]
FROM Transfer_Table AS T
GROUP BY T.OrderID
) AS T ON O.OrderID = T.OrderID
LEFT JOIN
(
SELECT R.OrderID,SUM(R.ReturnAmount) [Total]
FROM Return_Table AS R
GROUP BY R.OrderId
) AS R ON R.OrderId = O.OrderID

Joining multiple tables with filter

I got multiple tables and i'm only using 3 for testing. I don't know if this is the right approach.
AccntTbl
id accnt amount date
---------------------------------
1 xxx 10.00 1/1/2016
2 yyy 20.00 1/1/2016
3 zzz 30.00 1/1/2016
SupplyTbl
id accnt supply date
-------------------------------
1 xxx 5.00 1/10/2016
1 xxx 5.00 2/14/2016
IssuedTbl
id accnt issued date
---------------------------------
1 xxx 3.00 1/9/2016
1 xxx 2.00 2/1/2016
and the result will be like this if filter to JANUARY
id accnt amount issued balance
--------------------------------------------
1 xxx 15.00 3.00 12.00
2 yyy 20.00 0.00 20.00
3 zzz 30.00 0.00 30.00
and if FEBRUARY
id accnt amount issued balance
---------------------------------------------
1 xxx 20.00 5.00 15.00
2 yyy 20.00 0.00 0.00
3 zzz 30.00 0.00 0.00
and here's my query that i've come up with
SELECT accnttbl.id,
accnttbl.accnt,
Sum(accnttbl.amount)
+ Sum(SupplyTbl.supply) AS amount,
issuedtbl.issued
FROM accnttbl
LEFT JOIN (SELECT id,
Sum(supply) AS supply,
date
FROM supplytbl
GROUP BY id,
date) AS SupplyTbl
ON accnttbl.id = SupplyTbl.id
AND Month(SupplyTbl.date) BETWEEN 1 AND 2
LEFT JOIN (SELECT id. Sum(issued) AS issued,
date
FROM issuedtbl
GROUP BY id,
date)
ON accnttbl.id = issuedtbl.id
AND Month(issuedtbl.date) BETWEEN 1 AND 2
WHERE Year(accnttbl.date) = 2016
GROUP BY accnttbl.id,
accnttbl.accnt
and i kinda mess up..glad for any help :)
the result be like this..in JANUARY
id accnt amount issued
1 xxx 30.00 10.00
2 yyy 20.00 0.00
and in FEBRUARY
1 xxx 60.00 20.00
2 yyy 20.00 0.00
with the value that i been given..it just..it doubled the amount on its own..the result are wrong..why is that ?
Try as below :
SELECT AccntTbl.id, AccntTbl.accnt
, SUM(AccntTbl.amount) + SUM(SupplyTbl.supply) as amount
, SUM(IssuedTbl.issued) as issued
, (SUM(amount) - SUM(issued)) as balance
FROM AccntTbl LEFT JOIN
(SELECT id, COALESCE(SUM(supply), 0) AS supply, date FROM SupplyTbl
GROUP By id, date) AS SupplyTbl
ON AccntTbl.id = SupplyTbl.id AND (MONTH(SupplyTbl.date) BETWEEN
1 AND 2)
LEFT JOIN
(SELECT id, COALESCE(SUM(issued),0) as issued, date from IssuedTbl
GROUP By id, date )
ON AccntTbl.id = IssuedTbl.id AND (MONTH(IssuedTbl.date) BETWEEN
1 AND 2)
WHERE (YEAR(AccntTbl.date) = 2016)
GROUP By AccntTbl.id, AccntTbl.accnt
;
In sql anything added with NULL is NULL . So in your subquery if you are not using COALESCE, you are adding your value with NULL, hence you are not getting your desired result.