SQL Help, Splitting Tax by Tenders - sql

I have a Point of Sale system where all checks and tender details exist in a single table. I'm trying to write a SQL query in a way that I can see check totals by tenders to reconcile with cash flow and bank statements. Unfortunately the schema is not mine and can't change it.
One problem I ran into is that there are cases where one check has multiple transactions involving various tenders, therefore I need to do implement (business set) rules to allocate taxes evenly. Those rules might change in the future to say, allocate taxes to CC first if any, so I need to built in some flexibility.
The SQL table looks like this:
CheckID
LineType
TenderName
LineTotal
Tax
1
ItemSold
5.00
0.25
1
TenderTotal
Cash
5.25
2
ItemSold
10.00
0.50
2
TenderTotal
Cash
5.00
2
TenderTotal
VISA
5.50
3
ItemSold
10.00
0.25
3
ItemSold
10.00
0.25
3
TenderTotal
AMEX
10.25
3
TenderTotal
VISA
10.25
4
ItemSold
10.00
0.50
4
TenderTotal
Cash
20.00
4
TenderTotal
Cash
-9.50
The resulting report needs to have one row per tender, with tax equally distributed among check tenders, and net revenue being the difference between total sale and tax.
TenderName
TotalSale
NetRevenue
TaxCollected
Cash
20.75
19.75
1.00
VISA
15.75
15.25
0.50
AMEX
10.25
10.00
0.25
I tried using Select with Exists, also CTE and recursive CTEs, but can't quite figure it out how to do the tax part cleanly. Any other SQL tricks I could try?
We are using SQL Server 2012 at the moment, but have plans in plan to upgrade to 2016 in the near future.

I don't know if the logic is right, but it gets you the results you are after:
WITH Tenders AS(
SELECT V.CheckID,
V.LineType,
V.TenderName,
V.LineTotal,
SUM(CASE WHEN V.TenderName IS NULL THEN V.Tax END) OVER (PARTITION BY V.CheckID) AS Tax
FROM (VALUES(1,'ItemSold',NULL,5.00,0.25),
(1,'TenderTotal','Cash',5.25,NULL),
(2,'ItemSold',NULL,10.00,0.50),
(2,'TenderTotal','Cash',5.00,NULL),
(2,'TenderTotal','VISA',5.50,NULL),
(3,'ItemSold',NULL,10.00,0.25),
(3,'ItemSold',NULL,10.00,0.25),
(3,'TenderTotal','AMEX',10.25,NULL),
(3,'TenderTotal','VISA',10.25,NULL),
(4,'ItemSold',NULL,10.00,0.50),
(4,'TenderTotal','Cash',20.00,NULL),
(4,'TenderTotal','Cash',-9.50,NULL))V(CheckID,LineType,TenderName,LineTotal,Tax))
SELECT T.TenderName,
SUM(T.LineTotal) AS TotalSale,
SUM(T.LineTotal - T.Tax) AS NetRevenue,
SUM(T.Tax) AS TaxCollected
FROM Tenders T
WHERE T.TenderName IS NOT NULL
GROUP BY T.TenderName;

Related

How to handle the stock table quantity after sale

I have a problem. I am not understanding that how to deduct the quantity from stock after sale and we have multiple entries of same stock
like:
id
Medicine
Company
quantity
item price
is deleted
1
Panadol
Abbott
200
10.00
0
2
Panadol
Abbott
100
11.00
0
3
Panadol
Abbott
100
12.00
0
now how to deduct the quantity of stock and one thing is more that this product/Medicine has separate manufacturing and expiry date
please tell me how to handle it.
I was thinking that to make separate table for tracking the remaining stock quantity.
or runtime management to calculate all the sale quantity minus(-) sum of all quantities entered to get
the current stock quantity.
Please guide me.

Automated Monthly data generation in SQL

I'm fairly new in ASP.NET and MSSql and I came across a problem, I have a House Rent payment system where I want to automatically generate a certain reminder like Pay-Rent at the starting of every month where I already have the transaction of payment of rent and return of advanced money given to the land-lord by the tenant after the first day of the month
...currently my database shows this
EntryDate Transaction Advance Rent Paid Description Advanced
Return
2021-01-27 Rent Paid 0.00 2000.00 2k rent received 5000.00
2021-02-20 Rent Paid 0.00 9000.00 9000 rent paid 5000.00
2021-03-10 Rent Paid 0.00 100.00 100 rent paid 5000.00
2021-04-6 Rent Paid 0.00 99.00 99 amount paid 5000.00
2021-05-2 Advanced Money Returned 1000.00 0.00 1000 rent returned 5000.00
...what i want to do is this
EntryDate Transaction Rent Advance RentPaid Description Advanced
Return
2021-01-01 Please Pay your rent 5000 0 0 0 0
2021-01-27 Rent Paid 0 0.00 5000.00 5k rent received 5000.00
2021-02-01 Please Pay your rent 5000 0 0 0 0
2021-02-20 Rent Paid 0 0.00 5000.00 5k rent paid 5000.00
2021-03-01 Please Pay your rent 5000 0 0 0 0
2021-03-10 Rent Paid 0 0.00 5000.00 5k rent paid 5000.00
2021-04-01 Please Pay your rent 5000 0 0 0 0
2021-04-6 Rent Paid 0 0.00 5000.00 5k amount paid 5000.00
2021-05-01 Please Pay your rent 5000 0 0 0 0
2021-05-2 Advanced Money Returned 0 1000.00 5000.00 5k rent returned 5000.00
this line which i want is to be autogenerated at the beginning of each month
2021-01-01 Please Pay your rent 5000 0 0 0 0
and this is the code of my StoredProcedure
SELECT RR.EntryDate, (N'RentPaid') as TransactionName, 0 as AdvanceReturn, RR.AmountPaid as RentPaid, RR.Description,MemberStartAmount as Advanced
FROM tblRentReceive as RR WHERE UserId = #UserId
UNION ALL
SELECT OGF.EntryDate, (N'Advanced Money Returned') as TransactionName, AR.Amount as Amount, 0 as RentReceive, AR.Description,
#MemberStartAmount as Advanced
FROM tblAdvancedReturn as AR WHERE AR.UserId = #UserId and AR.TenantId=#TenantId
ORDER BY EntryDate ASC
END
END
Where do i need to add that automated monthly row without breaking my union between two tables
The pseudo code:
START
for each record in master-record
begin
get the %MONTH% and %YEAR% of the record
create new record with day:1, month=%MONTH%, and year=%YEAR%, Transaction='Please pay your rent', and etc.
add the record and calculate the balance
end
add final-record 'Advanced Money Record' with the calculated balance
END
If you got the idea, you can translate it to tsql-stored-proc.

Display order count using oracle

I show my table structure below. I want the record like the second structure. Please help me to get this using oracle or SQL.
FLd_Date Fld_Via Fld_Amt
11/1/2013 cash 100.26
11/2/2013 online 123.00
11/3/2013 cash 32.00
11/4/2013 cash 234.00
11/5/2013 cash 125.00
11/6/2013 online 125.00
11/7/2013 cash 200.00
11/8/2013 online 111.00
11/9/2013 online 143.00
11/10/2013 cash 155.00
11/11/2013 online 12.00
11/12/2013 online 142.00
I want the output like this
mode count total
cash 6 846.26
online 6 656
select fld_via as mode,
count(*) as count,
sum(fld_amt) as total
from your_table
group by fld_via
Please try:
select
Fld_Via as "mode",
count(*) as "count",
sum(Fld_Amt) as "total"
from
YourTable
Group by Fld_Via

Using multiple tables to find cost by transactiondate and location

I am trying to create a query that joins 3 tables with multiple prices and locations. Ex of the data I'm pulling.
Table A - product, product name
Table B - transactionid, date, product, returnreason, quantity, costprice, costamount,
location, journalid
Table C - price1, price2, price3, price4, price5, price6, product, activedate
Table C is updating prices for our products and can be the same from one date to another, or completely change depending on the market. Location in Table B can be up to four different locations.
Ex. Table C (each product is setup basically the same in the tables.)
product price1 price2 price3 price4 price 5 price6 activedate
A 0.00 0.00 0.00 0.00 0.00 0.00 1/1/11
A 0.00 0.00 0.00 0.00 0.00 0.00 2/1/11
A 1.00 0.00 0.63 0.00 1.20 0.20 1/1/12
A 1.20 0.53 0.01 1.00 0.42 0.00 4/1/13
Table B
product transactionid tdate returnreason quantity costprice costamount location journalid
A 00001 5/1/11 def 100 2.00 2.50 100 000010
B 00205 6/13/11 col 250 10.00 15.00 300 000320
A 00207 4/11/13 col 50 5.00 1.50 100 000720
I need to get the information out by the most current price for the item by date. So if I need a yearly report, I can see that for product A - price1 for 1/1/13-4/30/13 was 1.00 and for 5/1/13-present the price is now 1.20.
I have tried many things including sub queries and the latest (which is closest) to limit it by creating a where statement to be activedate<=tdate which will bring me every active date below and equal to the tdate. For this please assume product A is at location 100. How can I limit to the product active during the time frame it would be active?
Most recent...
I added line number in to make sure I got each line of the journal in...just visual.
select distinct(b.transactionid), b.tdate, b.linenum b.product, b.location,
b.journalid, c.price1, c.price2, c.price3, c.price4, c.price5, c.activedate
from Table b inner join
Table c on c.product=b.product
where c.activedate <= b.tdate
When I run this I get all dates that were less than the transaction date, but I need specific. For example the first transaction in my example, it happened on 5/1/11, when I run the query it will give me the results from table c for 1/1/11 and 2/1/11. I just need the date of the price for when the transaction took place.

Determining if value is between two other values in the same column

I'm currently working on a project that involves using a user-provided charge table to calculate fees.
The table looks like:
MaxAmount Fee
10.00 1.95
20.00 2.95
30.00 3.95
50.00 4.95
As seen in the table above, any MaxAmount up to 10.00 is charged a 1.95 fee. Any MaxAmount between 10.01 and 20.00 is charge a 2.95 fee, etc. Finally, any MaxAmount above 50.00 is charged 4.95.
I'm trying to come up with a sql query that will return the correct fee for a given MaxAmount. However, I'm having trouble doing so. I've tried something similar to the following (assuming a provided MaxAmt of 23.00):
SELECT Fee FROM ChargeTable WHERE 23.00 BETWEEN MaxAmt AND MaxAmt
Of course, this doesn't give me the desired result of 3.95.
I'm having trouble adapting SQL's set-based logic to this type of problem.
Any and all help is greatly appreciated!
If the MaxAmount behaves as the table suggests, then you can use:
select top 1 fee
from ChargeTable ct
where #Price <= MaxAount
order by MaxAmount desc
As you describe it, you really want another row:
MaxAmount Fee
0.00 1.95
10.00 1.95
20.00 2.95
30.00 3.95
50.00 4.95
Your original table does not have enough values. When you have 4 break points, you actually need 5 values -- to handle the two extremes.
With this structure, then you can do:
select top 1 fee
from ChargeTable ct
where #Price >= MaxAount
order by MaxAmount desc
You could try something like:
SELECT min(Fee) FROM Fees WHERE 23<=MaxAmount
Have a look here for an example:
http://sqlfiddle.com/#!2/43f2a/5