Calculation of interest on balance due - sql-server-2017

I have 3 tables Invoice, Payments and InterestRate. For purposes of simplicity I am representing each of the tables as follows.
The Invoice table has the following columns (the InvNum is the primary key)
+--------------+-------------+---------------+
| InvNum | InvDate | InvAmt |
+--------------+-------------+---------------+
| 123 | 2017-03-09| 15000 |
| 456 | 2017-01-13| 20000 |
+--------------+-------------+---------------+
The Payment table is as follows (the InvNum in the payments table is a foreign key which links to the Invoice table above
+--------------+------------+----------+
| payment_date | InvNum | amount |
+--------------+------------+----------+
| 2017-08-10 | 123 | 5000 |
| 2017-08-15 | 456 | 3000 |
| 2017-09-15 | 123 | 3000 |
| 2017-10-11 | 456 | 4000 |
| 2017-10-16 | 123 | 3500 |
| 2017-11-10 | 123 | 3000 |
| 2017-11-15 | 456 | 2500 |
+--------------+------------+----------+
My InterestRate looks something like this
+--------------+-------+
| ResetDate | IntRate|
+--------------+--------+
| 2016-01-01| 10 |
| 2017-06-08| 10.25 |
| 2017-11-03| 10.67 |
| 2018-05-03| 10.83 |
| 2018-07-29| 10.72 |
| 2019-01-01| 10.67 |
+------------+----------+
What I need is to calculate the interest for each Invoice after considering each payment and the final balance due on the invoice (in case it has not been fully paid). The final table should look something like this
InvNum IntFrom IntTo Amount IntRate Interest Payment Balance
123 2017-03-09 2017-06-07 15000 10 xxx 0 15000
123 2017-06-08 2017-08-10 15000 10.25 yyy 5000 10000
123 2017-08-11 2017-09-15 10000 10.25 zzz 3000 7000
123 2017-09-16 2017-10-16 7000 10.25 aaa 3500 3500
123 2017-10-17 2017-11-02 3500 10.67 bbb 0 3500
123 2017-11-03 2017-11-15 3500 10.67 ccc 2500 1000
123 2017-11-16 2018-05-02 1000 10.67 ddd 0 1000
123 2018-05-03 2018-07-28 1000 10.83 eee 0 1000
123 2018-07-29 2018-12-31 1000 10.72 fff 0 1000
123 2019-01-01 (today) 1000 10.67 ggg 0 1000
I have not shown the results of Inv#456. But the desired solution needs to group each of the invoices in the invoice table.
So in effect the interest calculation takes into account the payments made against each invoice (listed in the Payments table) as well as the changing interest rates (listed in the InterestRate table). Of equal importance is the fact that the interest on the balance due on each invoice (1000 for inv#123) needs to calculated till the date of running the query.
One of the challenges I am also facing is how can I capture the above results in a table. Would it mean dropping and recreating the table every time you run the query (since everytime the date changes the interest amount on the balance due will undergo a change). So unless only the interest on the balance per invoice can be updated, it would (should?) necessarily mean that the table has to be dropped and re-created. Alternatively, the results have to be viewed through a view query.
I hope I have been able to articulate my problem satisfactorily.
Thanks a lot for your time and attention to helping me out

Related

Calculating COGS to finish stock balance report SQL

I have two source table as following: Purchase & Sale
purchase (incoming)
--------------+----------+-------+----------+--------------
inventory_id | quantity | price | Amount | timestamp
--------------+----------+-------+----------+--------------
A | 1 | $1.00 | $1.00 | 2020-02-01
B | 2 | $1.00 | $2.00 | 2020-02-02
C | 4 | $2.00 | $8.00 | 2020-02-03
--------------+----------+-------+----------+--------------
sale (outgoing)
--------------+----------+-------+----------+--------------
inventory_id | quantity | price | Revenue | timestamp
--------------+----------+-------+----------+--------------
A | 1 | $3.00 | $3.00 | 2020-02-04
B | 1 | $3.00 | $3.00 | 2020-02-05
C | 2 | $3.00 | $6.00 | 2020-02-05
C | 1 | $3.00 | $3.00 | 2020-02-07
--------------+----------+-------+----------+--------------
What I want to do is the balance report in the below format:
Balance Report (2020-02-02 to 2020-02-05)
--------------+-----------+-------------+-------------+---------------+-----------+------------+---------+------------+
inventory_id | Begin Qty | Begin Amount| Purchase Qty|Purchase Amount| Sale Qty | COGS Amount | End Qty | End Amount |
--------------+-----------+-------------+-------------+---------------+-----------+------------+---------+------------+
A | 1 | $1.00 | | | 1 | $1.00 | | |
B | | | 2 | $2.00 | 1 | $1.00 | $1.00 | $1.00 |
C | | | 4 | $8.00 | 2 | $4.00 | $2.00 | $4.00 |
--------------+-----------+-------------+-------------+---------------+-----------+------------+---------+------------+
Note: The last outgoing transaction is out of the Report time range (2-05/02/2020) then not showing on the report.
MY CURRENT SOLUTION:
Add one column 'COGS' in the Sale table
I have to calculate the COGS of all inventory_id in the current sale order
Then save the COGS to the server with other information of sale order
THE PROBLEM:
If there is any change of the past transactions in the Purchase or Sale order, the COGS column does not UPDATE.
I NEED HELP ON:
Case 1: Keep COGS Column in the Sale table
How to update the value in this column if pasts transactions changed?
Case 2: Remove COGS Column
Pls help me to write a query to calculate the Sale Amount column in the Balance Report (Moving average is ok)
It would be great if you could provide the query to calculate the Sale Amount column by FIFO, LIFO.
Thanks a lot.
I found the solution: "I need to update COGS unit price for every transaction"
Following is the main code to update COGS
You might need to change something to adapt your case.
I know it is not the best solution but for my case it is ok.
create procedure update_COGS
as
update Sale
set
Sale.price = b.Aprice
from
Sale a
left join (select code, SUM(quantity) as quantity, sum(amount) as amount, SUM(amount)/nullif(sum(quantity),0) as Aprice from Purchase group by code) b
on a.code = b.code

How to join transactional data with customer data tables and perform case-based operations in SQL

I'm trying to perform a query between two different tables and come up with a case by case scenario, coming up with a list of records of calls for a specific month.
Here are my tables:
Customer table:
+----+----------------+------------+
| id | name | number |
+----+----------------+------------+
| 1 | John Doe | 8973221232 |
| 2 | American Dad | 7165531212 |
| 3 | Michael Clean | 8884731234 |
| 4 | Samuel Gatsby | 9197543321 |
| 5 | Mike Chat | 8794029819 |
+----+----------------+------------+
Transaction data:
+----------+------------+------------+----------+---------------------+
| trans_id | incoming | outgoing | duration | date_time |
+----------+------------+------------+----------+---------------------+
| 1 | 8973221232 | 9197543321 | 64 | 2018-03-09 01:08:09 |
| 2 | 3729920490 | 7651113929 | 276 | 2018-07-20 05:53:10 |
| 3 | 8884731234 | 8973221232 | 382 | 2018-05-02 13:12:13 |
| 4 | 8973221232 | 9234759208 | 127 | 2018-07-07 15:32:30 |
| 5 | 7165531212 | 9197543321 | 852 | 2018-08-02 07:40:23 |
| 6 | 8884731234 | 9833823023 | 774 | 2018-07-03 14:27:52 |
| 7 | 8273820928 | 2374987349 | 120 | 2018-07-06 05:27:44 |
| 8 | 8973221232 | 9197543321 | 79 | 2018-07-30 12:51:55 |
| 9 | 7165531212 | 7651113929 | 392 | 2018-05-22 02:27:38 |
| 10 | 5423541524 | 7165531212 | 100 | 2018-07-21 22:12:20 |
| 11 | 9197543321 | 2983479820 | 377 | 2018-07-20 17:46:36 |
| 12 | 8973221232 | 7651113929 | 234 | 2018-07-09 03:32:53 |
| 13 | 7165531212 | 2309483932 | 88 | 2018-07-16 16:22:21 |
| 14 | 8973221232 | 8884731234 | 90 | 2018-09-03 13:10:00 |
| 15 | 3820838290 | 2093482348 | 238 | 2018-04-12 21:59:01 |
+----------+------------+------------+----------+---------------------+
What am I trying to accomplish?
I'm trying to compile a list of "costs" for each of the customers that made calls on July 2018. The costs are based on:
1) If the customer received a call (incoming), the cost of the call is equal to the duration;
2) if the customer made a call (outgoing), the cost of the call is 100 if the call is 30 or less in duration. If it exceeds 30 duration, then the cost is 100 plus 5 * duration of the exceeded period.
If the customer didn't make any calls during that month he shouldn't be on the list.
Examples:
1) Customer American Dad has 3 incoming calls and 1 outgoing call, however only trans_id 10 and 13 are for the month of July. He should be paying a total of 538:
for trans_id 10 = 450 (100 for the first 30s + 5 * 70 for the remaining)
for trans_id 13 = 88
2) Customer Samuel Gatsby has 1 incoming call and 3 outgoing calls, however only trans_id 8 and 11 are for the month of July. He should be paying a total of 722:
for trans_id 8 = 345 (100 for the first 30s + 5 * 49 for the remaining)
for trans_id 11 = 377
Considering only these two examples, the output would be:
+----+----------------+------------+------------+
| id | name | number | billable |
+----+----------------+------------+------------+
| 2 | American Dad | 7165531212 | 538 |
| 4 | Samuel Gatsby | 9197543321 | 722 |
+----+----------------+------------+------------+
Note: Mike Chat shouldn't be on the list as he didn't make or receive any calls for that specific month.
What have I tried so far?
I've been playing cat and mouse with this one, I'm using the number as uniqueID, already attempted both a full outer join and combining where incoming or outgoing is not null then applying rules by case, tried doing a left join and applying cases, but I'm circling around and I can't get to a final list. Whenever I get incoming or outgoing, I'm either not able to apply the case or not able to come with both together. Really appreciate the help!
select customer_name.name, customer_name.number, bill = (CASE
WHEN customer_name.number = transaction_data.incoming then 'sum bill'
else 'multiply and add'
end)
from customer_name
left join transaction_data on customer_name.number = transaction_data.incoming or customer_name.name = transaction_data.outgoing
where strftime('%Y-%m', transaction_data.date_time) = '2018-07'
Note: I'm using sqlite to try it out online but the database is on SQL Server 2012, so I know that I can use a date format much easier, that way, but I'd like to keep as close to T-SQL as possible.
Also tried creating a case to determine whether it's incoming call or outgoing, but I'm only getting incoming as a result, even though trans_id 10 is outgoing:
select name, number, duration, case
when customer_name.number = transaction_data.incoming then 'incoming'
when customer_name.number = transaction_data.outgoing then 'outgoing'
END direction
from customer_name
left join transaction_data on customer_name.number = transaction_data.incoming or customer_name.name = transaction_data.outgoing
where strftime('%Y-%m', transaction_data.date_time) = '2018-07'
Try this:
SELECT
c."name", c.number,
SUM(CASE c.number
WHEN t.incoming THEN t.duration
ELSE IIF(t.duration - 30 < 0, 0, t.duration - 30) * 5 + 100
END) AS billable
FROM Customer AS c INNER JOIN [Transaction] AS t
ON c.number IN(t.incoming, t.outgoing)
WHERE t.date_time >= '20180701' AND t.date_time < '20180801'
GROUP BY c."name", c.number
Output:
| name | number | billable |
+---------------+------------+----------+
| John Doe | 8973221232 | 440 |
| American Dad | 7165531212 | 538 |
| Michael Clean | 8884731234 | 774 |
| Samuel Gatsby | 9197543321 | 722 |
Test it online with SQL Fiddle.

DAX: Avoid summing up repeated numbers

I have a table that includes columns for accountID, revenue, quarter and estimated revenue. the issue with this table is that the revenue repeats for each quarter.
The table is perfect if I'm trying to find the estimate, but as soon as I sum the revenue, it basically quadruples for each account.
I can divide by 4, but that gives a wrong revenue number for each quarter.
Is there a DAX function that allows me to show "4000" for each quarter, but at account/company level, it would not quadruple in size?
AccountID | Revenue | Quarter | Estimate
123 | 4000 |Q1 | 4000
123 | 4000 |Q2 | 5000
123 | 4000 |Q3 | 2000
123 | 4000 |Q4 | 4000
456 | 3000 |Q1 | 4000
456 | 3000 |Q2 | 5000
456 | 3000 |Q3 | 1000
456 | 3000 |Q4 | 3000
What I would like to see in pivot
Account ID | Quarter | Sum of Revenue | Sum of Estimate
123 | Q1 |4000 | 4000
123 | Q2 |4000 | 5000
123 | Q3 |4000 | 2000
123 | Q4 |4000 | 4000
123 Total |4000 | 15000
456 | Q1 |3000 | 4000
456 | Q2 |3000 | 5000
456 | Q3 |3000 | 1000
456 | Q4 |3000 | 3000
456 Total |3000 | 13000
Grand Total |7000 | 2800
Create two measures EstimateMeasure and RevenueMeasure:
EstimateMeasure = SUM(Table1[Estimate])
RevenueMeasure = SUMX(VALUES(Table3[Revenue]),Table3[Revenue])
Add previously created measures to Values and AccountID & Quarter in your pivot table.
It should produce the following output in Power BI.
Note I don't have access to PowerPivot in this moment, so I can't post the complete table with subtotals. But you can add subtotals in PowerPivot to get the total per AccountID.
Let me know if this helps.

How can I perform this in a single query

In SQL Server 2008, I have something similar to this:
Accounts:
aaa | 01/01/2010 | 15.00
bbb | 01/01/2010 | 20.00
ccc | 01/01/2010 | 10.00
ddd | 02/01/2010 | 30.00
eee | 04/01/2010 | 25.00
fff | 05/01/2010 | 1.00
Transactions:
aaa | 01/01/2010 | 15.00
aaa | 02/01/2010 | 20.00
aaa | 03/01/2010 | 5.00
bbb | 01/01/2010 | 15.00
bbb | 04/01/2010 | 5.00
ccc | 04/01/2010 | 10.00
ddd | 05/01/2010 | 25.00
I need the results to be something like:
Jan-10 Feb-10 Mar-10 Apr-10 May-10 Accts tot Trans Tot
Jan-10 15 20 5 5 0 45 45
Feb-10 15 0 0 15 0 30 30
Mar-10 0 0 0 0 0 0 0
Apr-10 0 0 0 0 0 25 25
May-10 0 0 0 0 0 0 0
I hope that makes sense... Each cell is the sum of the transactions for accounts created in a certain month. So accounts created in January will have a transaction total each month for the year. The first column is the account date, the row is the transaction date, and the cells are sums anytime an account created in that month has a transaction in the corresponding month.
Right now I do a join on the tables, then loop through and calculate each cell.
The loop is killing my processing time.
I don't think that you'll find a query to return that. Many years ago I was an expert in sqlServer but I've forgot many things about transact-sql, what I did when I had those kind of problems was to create a temporary table with the columns needed based on a query and start inserting the information, using cursors to loop the information. At the end just a "select * from #temp". Hope this idea helps...

MS ACCESS Cross table DATA

I have two tables, one with employee details looks like this
Employee ID | Employee Name | Start Date | Termination Date |
2234 | John Smith | 2014-01-03 | |
3333 | Jane Doe | 2014-04-22 | 2014-10-31 |
1234 | Bobby Wilson | 2013-12-10 | |
My second table has there sales by month-year
looks like so
Employee ID | 2013-12 | 2014-01 | 2014-02 | 2014-03 | 2014-04 | etc | etc
2234 | | 199.99 | 130.00 | 300.00 | 230.99 | etc | etc
3333 | | | | | 204.02 | etc | etc
1234 | 455.99 | 332.32 | 334.00 | 553.00 | 334.99 | etc | etc
So what i need is to make a new Query that helps me show the trend of the employee on how their first month employeed sales number looks like, second month sales, third moneth sales etc. based on when the month one being when the employee started. Over a spand of 12 month or more
So the new table would look as follows
Employee | Month 1 | Month 2 | Month 3 | Month 4 | etc | etc |
2234 | 199.99 | 130.00 | 300.00 | 230.99 | etc | etc |
3333 | 240.02 | (month 2) | (month 3)| (month 4)| etc | etc |
1234 | 455.99 | 332.32 | 334.00 | 553.00 | etc | etc |
So I know we can join the two tables by Employee ID
and I know we can determine an employee's month one based on their start date
but how do you write this query out in SQL?
As i mentioned in my comment to the question, you need to change the design of your second table as follow (pseudo-code):
CREATE TABLE Sales(
SaleId Autonumber PK
[Employee ID] FK (reference to Employees table)
SalesDate DateTime
Sales Decimal/Double
);
Then you'll be able to save your data this way:
SaleID EmpId SalesDate Sales
1 2234 2014-01-01 199,99
2 1234 2013-12-01 455.99
3 1234 2014-01-01 332.32
4 2234 2014-02-01 130
5 1234 2014-02-01 334
6 2234 2014-03-01 300
7 1234 2014-03-01 553
8 2234 2014-04-01 230.99
9 3333 2014-04-01 204.02
10 1234 2014-04-01 334.99
Finally, your pivot table might look like:
TRANSFORM Sum(S.Sales) AS SumOfSales
SELECT E.[Employee Id], E.[Employee Name]
FROM Employees AS E INNER JOIN SalesByMY AS S
ON E.[Employee Id] = S.[Employee Id]
GROUP BY E.[Employee Id], E.[Employee Name]
PIVOT 'Month-' & DateDiff('m',[E].[StartDate],[S].[SalesDate])+1;
The result:
EmpId EmpName Month-1 Month-2 Month-3 Month-4 Month-5
1234 Bobby Wilson 455.99 332.32 334 553 334.99
2234 John Smith 199.99 130 300 230.99
3333 Jane Doe 204.02