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;
I have a question about RDLC Report in NAV 2013
I have 2 rows like this
Store10 2.00 5.00 0.00 0.00
Store10 0.00 0.00 3.00 9.00
And I want 1 row by merging these, like;
Store10 2.00 5.00 3.00 9.00
How can it possible ?
Thanks for your answers.
First of all,
If rows first column is unique for your data. You should Group On this field in Visual Studio .
I couldn't add an image for reputation..
After that, Your line will shown merged. So, values maybe missing.
For calculating values effectively, You must use SUM(Field) syntax in "Table Cell Expression"
Like That
=SUM(Fields!RecNo.Value)
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
I am trying to get the next row's 'alignment' value and store it into the current row in a field called nextAlign. I have tried using grouping and also the unique identifier for this table is not consistent and doesn't always have an increment of 1. Here is some data:
type field starttop startleft length decimals alignment
-------------------------------------------------------------------------------------------
Text CUSTOMER DETAILS CONFIRMATION 13.00 38.00 30.00 0.00 Centre
Text Please spare a few minutes to 15.00 2.00 30.00 0.00 Left
Text confirm your details as held 15.00 2.00 30.00 0.00 Wrap
Text on our system. You may fax the 15.00 2.00 30.00 0.00 Wrap
Text form to the number above. 15.00 2.00 30.00 0.00 Wrap
Text Any information you may supply 17.00 2.00 30.00 0.00 Left
Text will not be made available to 17.00 2.00 30.00 0.00 Wrap
Text third parties according to the 17.00 2.00 30.00 0.00 Wrap
Text Privacy Act. 17.00 2.00 30.00 0.00 Wrap
Text Legal name: 20.50 2.00 30.00 0.00 Left
All I want is a column called 'nextAlign' that has the following data:
nextAlign
-Left
-Wrap
-Wrap
-Wrap
-Left
-Wrap
You didn't specify your DBMS, so this is ANSI SQL:
select type,
field,
align,
lead(align) over (order by starttop) as next_align,
starttop,
startleft
from the_table
use ROW_NUMBER() OVER(ORDER BY )
and outer join it to the same select this way: select_1_rownumber = select_2_rownumber+1
with temptable as
( select rownum
,type
,field
,starttop
,startleft
,length
,decimals
,alignment
from YOURTABLE )
select t.type
,t.field
,t.starttop
,t.startleft
,t.length
,t.decimals
,t.alignment
( select tt.alignment from temptable tt where tt.rownum = t.rownum+1 ) nextalign
from temptable t
Might work for you.
I am using SUM() function. But SUM() sums the negative value in the column. In a column if the value is positive then it should be added and for negative values should be substracted and not added as the SUM()
20.00
20.00
20.00
20.00
-20.00
20.00
20.00
40.00
20.00
20.00
20.00
20.00
20.00
-20.00
-20.00
20.00
sum() should return 220 and not 440.
Is returning 440.
To subtract negative numbers rather than add them you would use SUM(ABS(col)) but just to check this is what you actually need example results below.
WITH YourTable(col) AS
(
SELECT 2 UNION ALL
SELECT -5
)
SELECT
SUM(ABS(col)) AS [SUM(ABS(col))],
SUM(col) AS [SUM(col)]
FROM YourTable
Returns
SUM(ABS(col)) SUM(col)
------------- -----------
7 -3
SELECT SUM(ABS(Column_Name)) FROM Table_Name;