Applying percent change based on unique identifier - sql

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

Related

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='

Calculate column amount and get total with order number?

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

Transpose columns to rows and sum up common column

Basically I have these columns in a temp table, I would like to group them by the dynamic columns (Payment method) to rows and sum up the tax amount based on the payment method. The Tax column will always be there, so you may consider it a static column. The dynamic columns are stored in a variable #PaymentMethod = [Cash], [Card], etc...
Cash | Card | Tax
3.00 0.50
3.00 0.50
5.00 0.70
Expected result:
Pay Method | Tax
Cash 1.00
Card 0.70
How do I achieve this? I've looked up on UNPIVOT however, all the payment methods share the same Tax column field and that is actually the field I want to sum up.
Just use a case for aggregation:
select (case when cash is null and card is null then 'neither'
when cash is not null and card is not null then 'both'
when cash is not null then 'cash'
when credit is not null then 'credit'
end) as pay_method,
sum(tax)
from t
group by (case when cash is null and card is null then 'neither'
when cash is not null and card is not null then 'both'
when cash is not null then 'cash'
when credit is not null then 'credit'
end);

Accounting Overdue Query

I need a query to get open invoices and overdue (if any).
I have a table named "Invoices" with this basic structure:
InvoiceNo CustID InvoiceDate Amount DueDate Credit
1 1 01/04/2015 120.00 01/31/2015
2 2 01/13/2015 72.00 01/20/2015
3 1 01/12/2015 63.00 TRUE
4 2 02/18/2015 43.00 02/10/2015
5 2 02/24/2015 16.00 TRUE
A table named "Payments" reflecting the customers payments:
PaymentNo CustID PaymentDate Amount Refund
I have also an "Opening Balance" value for each customer
I need to be able to see on the query results of customers having a balance <> 0. Something like that:
CustID Balance Amount Overdue Days Overdue
I use this query to show open invoices, it works fine but I'm stuck with the overdue deal.
Select Customers.CustID
, Customers.DisplayName As 'Name'
, COALESCE(Customers.OpeningBalance,0)
+(( Select COALESCE(Sum(Invoices.Amount),0) From Invoices Where Credit = 0 And Invoices.CustID = Customers.CustID )
+( Select COALESCE(Sum(Payments.Amount),0) From Payments Where Refund = 1 And Payments.CustID = Customers.CustID ) )
-(( Select COALESCE(Sum(Invoices.Amount),0) From Invoices Where Credit = 1 And Invoices.CustID = Customers.CustID )
+( Select COALESCE(Sum(Payments.Amount),0) From Payments Where Refund = 0 And Payments.CustID = Customers.CustID )) as Balance
From Customers
Where Exists ( Select * From Invoices
Where Invoices.CustID = Customers.CustID )
#Zajonc
The overdue balance is calculated according to the invoice amount and the payment amount relatively to their dates.
Scenario:
assuming a customer has an invoice #1 with a due date dated 01/15/2015 and with the amount of 140.00
assuming that that customer made a payment of 40.00 on the 01/20/2015.
The days overdue would be the days between today and the due date.
The due date balance would be 140.00 - 40.00 = 100.00.
That's for only one invoice and one payment transaction but since the reality is a bit more complicated the calculation should reflects the accumulation of both of the days and balance overdue.ie:
Assuming we execute the query on 02/15/2015 with the following data on our customer:
Invoice # Amount Due Date
1 140.00 01/15/2015
2 360.00 02/08/2015
Payment # Amount Payment Date
1 40.00 01/20/2015
2 100.00 02/18/2015
The days overdue would be:
( days elapsed between 02/15/2015 and 01/15/2015 ) +
( days elapsed between 02/15/2015 and 02/08/2015 ) = 31 + 7 = 38 days.
The balance overdue would be 100.00 (the customer made a payment 3 days after the query's date ) + 360.00 = 460.00
I hope it clarifies.
Thanks.

How to join tables based on the dates

COMMISSION table
PRODUCT_ID DATE COMMISSION
1 20110101 27.00
1 20120101 28.00
1 20130705 30.00
2 20110101 17.00
2 20120501 16.00
2 20130101 18.00
...
ORDER table
PRODUCT_ID DATE PRICE
1 20110405 2500
2 20130402 3000
2 20130101 1900
Desired output
PRODUCT_ID DATE PRICE COMMISSION
1 20110405 2500 27.00
2 20130402 3000 16.00
2 20130101 1900 18.00
Commission table records commission % based on the product id and date.
Order table is basically a record of orders placed on a particular date,
I'd like to join two tables and bring the appropriate commission based on the date of the order. For example, you can see that the first order's commission is 27.00 as the date for the product_id 1 falls between 20110101 and 20120101.
How do I do this? Seems like a simple 1 to n relationship but I can't figure it out.
Try
SELECT o.*,
(
SELECT TOP 1 commission
FROM commission
WHERE product_id = o.product_id
AND date <= o.date
ORDER BY date DESC
) commission
FROM [order] o
Here is SQLFiddle demo