Finding sum based on the condition in Sql Server 2008 - sql

I have these columns in my table
Person Agent Unit BSP Discount
578 0 000023 32689525 0.1
578 1 000025 17589656 1
579 0 000021 32689525 0.1
579 0 000020 17589656 1
581 0 000022 32689525 0.1
583 0 000024 17589656 1
578 11 000023q 32689525 0
578 12 000025a 17589656 0
Actually I have to calculate the incentive for Person. Say in case of above 578. Since It has booked total 4 units out which 3 are with brokers and 1 is individual.
So from broker part his incentive will 2500 INR per unit that is 3*2500 = 7500.
Now comes the discount part. See the points below:
Conditions:
If No discount has been given, than 1% of BSP will be allocated to Incentive to the Sales Person.
If Discount given to booking is between .1% to 1%, than .75% of BSP will be allocated to Incentive to the Sales Person.
If Discount given to booking is between 1 .1% to 2%, than .50% of BSP will be allocated to Incentive to the Sales Person.
If Discount given to booking is between 2% and above, than .25% of
BSP will be allocated to Incentive to the Sales Person.
In the above tables it us clear that 578 has booked 4 units, two with discounts an two without discounts.
So his incentive will be calculated as :
var incentive = total_no_of_units_booked_with_agent * 2500;
// since there might be a possibility that more than one units can be
// booked by a sales person.No we have to find if there is any discount
// applied there, if its there, then extract the incentive for each unit
//and total it using the above condition. For table shown we have
//since it has 4 records
incentive = incentive + (.75% of BSP)+ (.75%of BSP)+(1% of BSP)+(1%of BSP)

For a conditional sum, just use SUM with a CASE statement inside it to enforce your conditions.
SELECT
person,
SUM(CASE WHEN discount = 0.00 THEN 0.0100 * bsp
WHEN discount <= 0.01 THEN 0.0075 * bsp
WHEN discount <= 0.02 THEN 0.0050 * bsp
ELSE 0.0025 * bsp END
+
CASE WHEN agent <> 0 THEN 2500.0
ELSE 0.0 END) AS incentive
FROM
yourTable
GROUP BY
person

Related

Computing ratio with two tables with multiple conditions

Table A
date
flight
airport
2012-10-01
oneway
ATL, GA
2012-10-01
oneway
LAX, CA
2012-10-01
oneway
SAN, CA
2012-10-01
oneway
DTW, MI
2012-10-02
round
SFO, CA
Table B
date
temp
precip
2012-10-01
67
0.02
2012-10-01
65
0.32
2012-10-01
86
0.18
2012-10-01
87
0.04
2012-10-02
78
0.24
The actual tables have more than 100k rows.
Exepected outcome has two columns temp and ratio
For each temp, I am trying to get the a ratio of flight = oneway where airport have "CA" in it.
I need to first filter rows that the average of precip is greater than 0.2 and cast ratio to interger.
I tried to join on date and group by temp that is having average precip < 0.2 but I am getting fixed wrong value on ratio.
How can I do CTE or CASE WHEN to merge these two tables to compute ratio?
Ratio is should be the (total count of all rows where flight = 'oneway' per each temperature after all filtering) / (total counts of rows)
In the query below I join A and B records over their Date matching as well as B.airport ending with CA, grouped by temperature. The total number of such pairs is the result of COUNT(*) that I divide with. The value I am dividing is the number of items from the pairs which have a oneway flight. It's possible that I did not fully understand the question, in which case we may need to move the airport criteria from the where into the case-when.
SELECT b.temp,
CAST(SUM(
CASE
WHEN A.flight = 'oneway'
THEN 1
ELSE 0
END
) AS FLOAT) / COUNT(*)
FROM A
JOIN B
ON A.`Date` = B.`Date` AND
B.airport LIKE '%CA'
GROUP BY B.temp

SQL Help, Splitting Tax by Tenders

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;

Distinct count for entire dataset, grouped by month

I am dealing with a sales order table (ORDER) that looks roughly like this (updated 2018/12/20 to be closer to my actual data set):
SOID SOLINEID INVOICEDATE SALESAMOUNT AC
5 1 2018-11-30 100.00 01
5 2 2018-12-05 50.00 02
4 1 2018-12-12 25.00 17
3 1 2017-12-31 75.00 03
3 2 2018-01-03 25.00 05
2 1 2017-11-25 100.00 17
2 2 2017-11-27 35.00 03
1 1 2017-11-20 15.00 08
1 2 2018-03-15 30.00 17
1 3 2018-04-03 200.00 05
I'm able to calculate the average sales by SOID and SOLINEID:
SELECT SUM(SALESAMOUNT) / COUNT(DISTINCT SOID) AS 'Total Sales per Order ($)',
SUM(SALESAMOUNT) / COUNT(SOLINEID) AS 'Total Sales per Line ($)'
FROM ORDER
This seems to provide a perfectly good answer, but I was then given an additional constraint, that this count be done by year and month. I thought I could simply add
GROUP BY YEAR(INVOICEDATE), MONTH(MONTH)
But this aggregates the SOID and then performs the COUNT(DISTINCT SOID). This becomes a problem with SOIDs that appears across multiple months, which is fairly common since we invoice upon shipment.
I want to get something like this:
Year Month Total Sales Per Order Total Sales Per Line
2018 11 0.00
The sore thumb sticking out is that I need some way of defining in which month and year an SOID will be aggregated if it spans across multiple ones; for that purpose, I'd use MAX(INVOICEDATE).
From there, however, I'm just not sure how to tackle this. WITH? A subquery? Something else? I would appreciate any help, even if it's just pointing in the right direction.
You should select Year() and month() for invocedate and group by
SELECT YEAR(INVOICEDATE) year
, MONTH(INVOICEDATE) month
, SUM(SALESAMOUNT) / COUNT(DISTINCT SOID) AS 'Total Sales per Order ($)'
, SUM(SALESAMOUNT) / COUNT(SOLINEID) AS 'Total Sales per Line ($)'
FROM ORDER
GROUP BY YEAR(INVOICEDATE), MONTH(INVOICEDATE)
Here are the results, but the data sample does not have enuf rows to show Months...
SELECT
mDateYYYY,
mDateMM,
SUM(SALESAMOUNT) / COUNT(DISTINCT t1.SOID) AS 'Total Sales per Order ($)',
SUM(SALESAMOUNT) / COUNT(SOLINEID) AS 'Total Sales per Line ($)'
FROM DCORDER as t1
left join
(Select
SOID
,Year(max(INVOICEDATE)) as mDateYYYY
,Month(max(INVOICEDATE)) as mDateMM
From DCOrder
Group By SOID
) as t2
On t1.SOID = t2.SOID
Group by mDateYYYY, mDateMM
mDateYYYY mDateMM Total Sales per Order ($) Total Sales per Line ($)
2018 12 87.50 58.33
I have used new SQL still MAX(INVOICEDATE)(not above), with new 12/20 data, and excluded AC=17.
YYYY MM Total Sales per Order ($) Total Sales per Line ($)
2017 11 35.00 35.00
2018 1 100.00 50.00
2018 4 215.00 107.50
2018 12 150.00 75.00

How to calculate Average based on a criteria on SSAS?

I've a Measure like below,
Year ProductCategory CompanyId TotalCustCnt SalesAmt Rank
2012 Prd1 1 20 100,000 1
2012 Prd2 1 10 75,000 2
2013 Prd1 2 18 80,000 2
2013 Prd2 2 15 50,000 1
Now I want to calculate three averages out of this data.
Average = SalesAmt / TotalCustCnt
Company average (Average for each company)
Leader average (Average for the leader for the Product category,year i.e company with Rank 1)
Industry average (Average for the whole industry for the product category,year)
The first one is straight forward, I've added a calculated field in the CUBE for adding an expression (SalesAmt / TotalCustCnt)
But how do I calculate the other two averages?
I've checked the AVG function and also tried SUM([Measures].[SalesAmt].ALLMEMBER) / SUM([Measures].[TotalCustCnt].ALLMEMBER) but no success.

Oracle SQL Paired Data

I need to find the difference in averages between patient weights at different visits (time points), but I'm struggling with finding the "paired" averages:
I have 1 table (PHYS) containing patient weights at different visits:
PATIENT VISIT WEIGHT
1 Baseline 200
1 1 Month 190
1 2 Month 170
2 Baseline 300
2 1 Month 290
2 2 Month 280
3 Baseline 250
3 1 Month 230
My problem is that I only want to find the difference for paired data. For example, when calculating the amount of weight loss between the 2 month and Baseline visits, I would want to find the difference between the (average 2 Month weight) and the (average Baseline weight FOR ONLY THOSE PATIENTS WITH A 2 MONTH WEIGHT). In this example, the result should be AVG(170,280) - AVG(200,300) = -25 (since only patient 1 and 2 have 2 Month weights).
Here is what I have, but it calculates the difference based on all weights:
SELECT VISIT
AVG(WEIGHT)
-
(SELECT
AVG(WEIGHT)
FROM PHYS
WHERE VISIT = 'BASELINE')
FROM PHYS
GROUP BY VISIT
My desired output would be (I know I need to add an ORDER BY):
VISIT CHANGE FROM BASELINE
Baseline 0
1 Month -13.3
2 Month -25
Thank you and sorry for such a newb question.
You can do this with a join to the same table but only for the 'Baseline'. Then, the aggregation only aggregates the values that match, so you should get different baseline averages for the three groups (because the populations are different):
select p.visit, avg(p.weight) as avg_weight, avg(pbl.weight) as avg_blweight,
(avg(p.weight) - avg(pbl.weight)) as change
from phys p join
phys pbl
on p.patient = pbl.patient and
pbl.visit = 'Baseline'
group by p.visit;