Subtract Daily amount from Withdraw Amount - sql

I have two tables, tblWithdraw and tblProfit.
tblWithdraw Table
WithdrawId Date User Price
-----------------------------------------------------
1 2021-02-09 SANDANUWAN 2000.00
2 2021-02-09 GAYAN 300.00
3 2021-02-09 KASUN 1500.00
4 2021-02-09 AMAL 4000.00
5 2021-02-09 UDARA 340.00
6 2021-02-09 SULIN 200.00
7 2021-02-09 PERERA 120.00
tblProfit Table
Id Date Inv.No ItemName ItemCode Qty CostPrice DiscountPrice Amount
----------------------------------------------------------------------------------------------
1 2021-02-09 INV0000001 DELL LAP LP001 5 1500.00 1900.00 9500.00
2 2021-02-09 INV0000001 HP MOUSE MO001 7 2500.00 2940.00 20580.00
3 2021-02-09 INV0000001 PACIFIC FAN FAN001 6 2000.00 4000.00 24000.00
4 2021-02-09 INV0000001 SAMSUNG PHONE PH001 8 1000.00 1350.00 10800.00
This is my question. I want to sum all price from tblWithdraw table according to the date. Its mean withdraw date and profit table must be match. New I want to sum all amount from tblProfit table.Then I want to Subtract like this Price - Amount. Finally I want to show total amount of Profit table after subtracted. I used following join but is not working well. please help me to solve this problem. I want to subtract according to the date.
Select MAX(w.Date)Date, SUM(w.Price)Price, SUM(p.Amount)Amount
From tblWithdraw w
Left Join tblProfit p
ON w.Date = p.CurrentDate
Group by w.Date
Out put is like this. its wrong.
Date Price Amount
2021-02-09 33840.00 454160.00

Here's my CTE-based approach based on the comment which I made on the initial question.
WITH WithDraw AS(
SELECT
[date]
,SUM(price) PRICE
FROM tblWithdraw
GROUP BY [date]
),
Profit AS(
SELECT
[date]
,SUM(amount)AMOUNT
FROM tblProfit
GROUP BY [date]
)
SELECT
W.DATE
,W.PRICE
,P.AMOUNT
FROM WithDraw W
INNER JOIN Profit P ON w.date = p.date;

I'm not sure I fully understand the question, this is how I'm reading it:
Select w.Date,
w.agg_price_by_date,
w.agg_price_by_date - COALESCE(p.agg_amount_by_date, 0) AS diff_price_amount
From (SELECT Date,
SUM(Price) AS agg_price_by_date
FROM tblWithdraw w
GROUP
BY Date
) w
Left Join
(SELECT CurrentDate,
SUM(Amount) AS agg_amount_by_date
FROM tblProfit
GROUP
BY CurrentDate
) p
ON w.Date = p.CurrentDate

Related

SQL Query to find price based on effective date only

Looking to find a SQL query that will work to join a few tables, where the price column will show the price for a specific date.
The data I'm working wiht only gives me the effective date, so I need to be able to say for product purchased on date X, the price should be Y
Here are my two tables:
Prices table:
Product
Price
Effective Date
Price code
123
$ 2.00
1/1/2020
W
177
$ 5.00
10/2/2021
W
123
$ 2.50
10/7/2021
W
123
$ 7.00
10/7/2021
A
500
$10.00
12/1/2021
W
123
$ 3.00
12/2/2021
W
Purchases table:
Product
Purchase Date
123
11/3/2021
123
12/7/2021
The output I am hoping to get:
Product
Purchase Date
Price
123
11/3/2021
$2.50
123
12/7/2021
$3.00
Here's the code I've tried so far that is not working:
FROM [dbo.Purchases] a
inner join [dbo].[Prices] b
on a.[Product] = b.[Product]
Where [Price code] = 'W'
and MAX(b.[Effective Date]) <= a.[Purchase Date]
select distinct pr.Product
,[Purchase Date]
,first_value(pr.Price) over(partition by pu.Product, pu.[Purchase Date] order by [Effective Date] desc) as Price
from Purchases pu join Prices pr on pr.Product = pu.Product and pr.[Effective Date] <= pu.[Purchase Date] and pr.[Price code] = 'w'
Product
Purchase Date
Price
123
2021-11-03 00:00:00.000
2.5000
123
2021-12-07 00:00:00.000
3.0000
Fiddle

Max and Avg debt days over a period of time

I have invoices pending payment, every invoice has two dates, first when the invoice is required to pay and the other when the invoice is paid. I want to know in a period of time the max debt and the avg debt
This is the table
Id Invoice Amount InvoiceDate InvoicePayment
----------- ------- ----------- ----------- -------------
1 Bill 1 314 2019-01-20 2019-03-01
2 Bill 2 205 2019-01-14 2019-02-18
3 Bill 3 90 2019-02-04 2019-02-06
4 Bill 4 456 2019-01-03 2019-04-27
I would like to know the max debt amount in february and the avg debt
You can unpivot with cross apply, and use a window sum to compute the "running" debt at each given point in time. The rest is just filtering and aggregation:
select avg(debt) avg_debt, max(debt) max_debt
from (
select x.dt, sum(x.amount) over(order by x.dt) debt
from mytable t
cross apply (values (invoicedate, amount), (invoicepayment, -amount)) as x(dt, amount)
) t
where dt >= '20200201' and dt < '20200301'

Calculate SUM between two dates SQL SERVER

I'm having two tables
Calendar
FirstDate | LastDate
------------+-----------
2020-05-01 2020-05-03
2020-05-02 2020-05-04
ProfileRate
ID | Date | Rate | Product
---+------------+------+----------
1 2020-05-01 100 Prod1
2 2020-05-02 200 Prod1
3 2020-05-03 300 Prod1
4 2020-05-04 400 Prod1
5 2020-05-01 150 Prod2
6 2020-05-02 250 Prod2
7 2020-05-03 350 Prod2
8 2020-05-04 450 Prod2
I want to calculate SUM. Something like this
FirstDate | LastDate | Prod1 | Prod2
------------+-------------+--------+-------
2020-05-01 2020-05-03 600 750
2020-05-02 2020-05-04 900 1050
What I've tried:
SELECT [Date], SUM([Rate])
FROM [ProfileRate]
WHERE [Date] BETWEEN '2020-05-01' AND '2020-05-04'
GROUP BY [Date]
Please help me. Thanks
you have to do several steps to solve the problem:
combine calendar records with profiles
establish which profiles meet the calendar range
total the value for each profile and date range
finally establish the detailed information of the calendar
this query meets the conditions
with DataForCalendar as
(
SELECT IdCalendar,FirstDate,LastDate,Id,DateRate,Rate,Product
FROM
Calendar CROSS JOIN ProfileRate
where DateRate between '2020-05-01' and '2020-05-05'
),
DetailForCalendar as
(
select IdCalendar,Rate,Product
from DataForCalendar
where DateRate between FirstDate and LastDate
),
TotalForCalendar as
(
select IdCalendar,Product,sum(Rate)As Total from DetailForCalendar
GROUP BY IdCalendar,Product
)
select Calendar.IdCalendar,Calendar.FirstDate,Calendar.LastDate,
TotalForCalendar.Product,TotalForCalendar.Total
from TotalForCalendar inner join
Calendar on TotalForCalendar.IdCalendar=Calendar.IdCalendar;
in this example you can find step by step how it work
in this example there is one more product and one more calendar.
I think this is a JOIN and conditional aggregation:
SELECT c.FirstDate, c.LastDate,
SUM(CASE WHEN pr.prod = 'Prod1' THEN pr.Rate END) as prod1,
SUM(CASE WHEN pr.prod = 'Prod2' THEN pr.Rate END) as prod2
FROM Calender c LEFT JOIN
ProfileRate pr
ON pr.Date >= c.FirstDate AND pr.Date <= c.LastDate
GROUP BY c.FirstDate, c.LastDate;
Do the join & conditional aggregation :
select c.fisrtdate, c.lastdate,
sum(case when pr.product = 'prod1' then rate else 0 end) as prod1,
sum(case when pr.product = 'prod2' then rate else 0 end) as prod2
from calendar c join
ProfileRate pr
on pr.date >= c.fisrtdate and pr.date <= c.lastdate
group by c.fisrtdate, c.lastdate;
If you want all calendar dates then use left join instead.

Selecting Account Numbers with latest date

I have been trying to solve this problem now for days.
I have table called Stat with the following simplified structure and sample data:
Customer BankID AccNumb Type Date Amount AccType
Customer 1 Boa 5 Account Statement 2015-01-01 10000,00 Eur
Customer 1 CS 10 Account Statement 2015-04-04 22000,00 Eur
Customer 2 Sa 15 Account Statement 2015-03-13 3000,00 Eur
Customer 2 Sa 40 Account Statement 2015-04-24 1000,00 Eur
Customer 2 Sa 15 Sale Advice 2015-04-16 400,00 Eur
Customer 2 Sa 15 Account Statement 2015-12-24 50,00 Usd
Customer 2 Boa 20 Sale Advice 2015-05-15 6000,00 Eur
Customer 3 Cu 25 Account Statement 2015-11-27 81000,00 Eur
Customer 3 Cu 30 Sale Advice 2015-11-27 3000,00 Usd
Customer 3 Pop 30 Account Statement 2015-11-27 12000,00 Eur
What I'm trying to do is to Select the AccountNumber with the latest date specified. A Customer can also have different Account Numbers on various Banks, so it should also be grouped by BankID and Customer.
I have come this far:
SELECT AccNumb, Customer, BankID,
(SELECT TOP 1 Amount FROM Stat
WHERE AccNumb = y.AccNumb AND Customer = y.Customer AND
BankID = y.BankID AND Type = 'Account Statement' AND
Date = MAX(y.Date) GROUP BY Amount) Amount
FROM Stat y
GROUP BY AccNumb, Customer, BankID
ORDER BY Customer, AccNumb
And it works fine, the problem is i should also add the column AccType and Date
I managed to do this with 2 more subselects (the query takes long but it works).
But now i have the problem that there are also NULL values in Customer (or Date) Column. Now, the account number of these 'NULL' Customers still should be displayed if it's the latest date. I also tried to do the same by joining the table by itself, and it didnt work out.
SELECT x.AccNumber, x.Customer, x.BankID, x.Date, y.Amount, y.AccType
FROM Stat y RIGHT JOIN
(SELECT AccNumber, Customer, BankID, MAX(Date) Date FROM Stat
GROUP BY AccNumber, Customer, BankID) x
ON x.AccNumber = y.AccNumber AND
x.Customer = y.Customer AND
x.BankID = y.BankID AND
x.Date = y.Date
ORDER BY y.Customer, y.AccNumber
But now the 'NULL' Customers only have NULL values in the Amount, Date and AccType Columns, which is not correct.
The output should be something like this
AccNumb Customer BankID Amount Date AccType
111111111 a Boa 1234.40 31.06.2014 Eur
222222222 NULL Boa 5678.40 31.04.2014 Eur
333333333 b Boa 0.00 25.02.2014 Eur
444444444 NULL Boa 9101.40 23.04.2015 Eur
555555555 NULL Boa 1213.40 31.02.2014 Usd
A66666666 c Sa NULL 31.02.2014 Eur
777777777 c Sa 1415.00 31.12.2014 Eur
888888888 c Boa 1617.40 31.12.2014 Usd
999999999 f Pop 5678.64 31.10.2014 Eur
Thanks in advance.
Just use row_number(), if I understand correctly:
select s.*
from (select s.*,
row_number() over (partition by customer, bankId order by date desc) as seqnum
from stat s
) s
where seqnum = 1;
Find the rows with latest dates, i.e. return a row if no other row with same AccountNumber, BankID and Customer but a later Date exists:
select *
from stat s1
where not exists (select 1 from stat s2
where s1.AccountNumber = s2.AccountNumber
and s1.BankID = s2.BankID
and s1.Customer = s2.Customer
and s1.Date < s2.Date)
You're first query works closely to what, I believe, you are looking for. Using it as a base, we can alter to work for you:
SELECT
AccNumb,
Customer,
BankID,
Amount,
Date,
AccType
FROM Stat y
WHERE Date = (SELECT MAX(z.DATE)
FROM Stat z
WHERE z.AccNumb = y.AccNumb
AND z.Customer = y.Customer
AND z.BankID = y.BankID AND Type = 'Account Statement')
ORDER BY Customer, AccNumb

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