Calculate fixed Cost/day for multiple services on same date - sql

Desired Output table T with Calculated Cost column:
SvcID Code ID Date Mins Units Cost
1 3000 15 4/4/2016 60 10 70
2 3000 17 4/4/2016 45 10 0
3 3000 15 5/2/2016 30 10 70
4 3000 18 5/2/2016 60 10 0
5 3000 10 5/2/2016 30 10 0
6 4200 16 2/1/2016 60 4 60
7 4200 9 2/1/2016 30 2 30
Query for calculating and displaying:
SELECT
...
,CASE
WHEN Code=4200 THEN Units*15
WHEN Code=3000 THEN ?
END AS Cost
FROM ...
WHERE Code IN ('3000','4200')
GROUP BY ....;
Cost should be a total of 70 for all services offered on same date for Code 3000, irrespective of number of services offered. No relation between Minutes and Units for this Code for calculating Cost.
One way could be to calculate cost as 70 for any one service and make the remaining services cost 0 for same date. Can this be done in the CASE statement?
Any better way to achieve this?

You need to Investigate Window functions MSDN.
Your case would become something like this:
-- New select statament
SELECT
...
,CASE
WHEN Code=4200 THEN Units*15
WHEN Code=3000 THEN ( CASE WHEN DuplicateNum = 1 THEN 70 ELSE 0 END )?
END AS Cost
FROM(
-- Your current query (with case statement removed) and ROW_NUMBER() function added
SELECT
..., ROW_NUMBER() OVER( PARTITION BY Code, Date ORDER BY ID ) AS DuplicateNum
FROM ...
WHERE Code IN ('3000','4200')
GROUP BY ....
) AS YourCurrentQuery;

Related

Finding Max Price and displaying multiple columns SQL

I have a table that looks like this:
customer_id item price cost
1 Shoe 120 36
1 Bag 180 50
1 Shirt 30 9
2 Shoe 150 40
3 Shirt 30 9
4 Shoe 120 36
5 Shorts 65 14
I am trying to find the most expensive item each customer bought along with the cost of item and the item name.
I'm able to do the first part:
SELECT customer_id, max(price)
FROM sales
GROUP BY customer_id;
Which gives me:
customer_id price
1 180
2 150
3 30
4 120
5 65
How do I get this output to also show me the item and it's cost in the output? So output should look like this...
customer_id price item cost
1 180 Bag 50
2 150 Shoe 40
3 30 Shirt 9
4 120 Shoe 36
5 65 Shorts 14
I'm assuming its a Select statement within a Select? I would appreciate the help as I'm fairly new to SQL.
One method that usually has good performance is a correlated subquery:
select s.*
from sales s
where s.price = (select max(s2.price)
from sales s2
where s2.customer_id = s.customer_id
);

Mean Of Sum Of Upper Rows

I expect someone could help me.
I made a table with some data, no need to know what in particual. I come from this #TempTable1:
WEEK_NUMBER SUM MEAN_OF_SUM
---------------------------------------------------------------------------
1 10
2 20
3 30
4 60
5 30
6 60
7 0
My desired table #TempTable1:
WEEK_NUMBER SUM MEAN_OF_SUM
---------------------------------------------------------------------------
1 10 10 --(10/1)
2 20 15 --(30/2)
3 30 20 --(60/3)
4 60 30 --(120/4)
5 30 30 --(150/5)
6 60 35 --(210/6)
7 0 30 --(210/7)
I tried with sums and expected the group by clause would work, but they do not. Does someone has an idea on how to solve this ?
I think are looking for a cumulative average:
select t.*, avg(sum*1.0) over (order by week_number)
from t;
This doesn't match the last value. I'm guessing that is a typo.

Combine multiple rows using SUM that share a same column value but has different other column values

I thought this would be a very simple query but for some reason, I can't seem to get the results I'm looking for. I have a table that has this structure. I just want a single entry for each account while summing the charges. I don't really care which date I keep, just one of them.
Account Charges Charges2 Date
1 100 50 1/1/2015
1 50 0 1/2/2015
2 50 0 2/4/2015
2 70 30 2/19/2015
3 100 0 1/12/2014
4 0 20 4/3/2015
4 40 20 4/9/2015
The result I want is:
Account Charges Charges2 Date
1 150 50 1/1/2015
2 120 30 2/4/2015
3 100 0 1/12/2014
4 40 40 4/3/2015
The result I currently get is:
Account Charges Charges2 Date
1 100 50 1/1/2015
2 70 30 2/19/2015
3 100 0 1/12/2014
4 40 40 4/9/2015
I thought this would be very simple and I tried below. But this doesn't sum them up, it just seems to return the rows where Charges2 is NOT 0.
SELECT Account, SUM(Charges) As TotCharges, SUM(Charges2) AS TotCharges2
FROM TABLE
GROUP BY Account
ORDER BY Account
You can apply the min() aggregate function to the date to limit the number of rows returned to one per account:
SELECT
Account,
SUM(Charges) AS TotCharges,
SUM(Charges2) AS TotCharges2,
MIN(Date) AS Date
FROM TABLE
GROUP BY Account
ORDER BY Account
Sample SQL Fiddle

Filter SQL query results by aggregrate

I need a query that shows the JobIDs where the Worker has not been paid BUT where the Company has been paid. Below are the table columns and sample data:
tblInvoices columns:
-------------------
JobID
InvoiceID
WorkerPaidAmountTotal
CompanyPaidAmountTotal
Sample data
-----------
JobID | InvoiceID | WorkerPaidAmountTotal | CompanyPaidAmountTotal
1 30 100 150
1 31 0 100
2 32 0 75
3 33 25 50
3 34 10 30
4 35 0 0
I know how to get the SUM of the amounts paid to either a Worker or the Company. The results look like this:
JobID Worker Company
1 100 250
2 0 75
3 35 80
4 0 0
But what I need are the results of just the JobIDs where the Worker has got 0 and the company >0. The results I want should be this, but I can't figure out the query to do so:
JobID Worker Company
2 0 75
Use HAVING clause to filter the groups. Try this :
SELECT jobid,
Worker=Sum(WorkerPaidAmountTotal),
Company=Sum(CompanyPaidAmountTotal)
FROM tablename
GROUP BY jobid
HAVING Sum(WorkerPaidAmountTotal) = 0
AND Sum(CompanyPaidAmountTotal) > 0
select jobid, worker, company where WorkerPaidAmountTotal = 0 and CompanyPaidAmountTotal
Seems to plain to do it... may be i did'nt understand the question

MySQL Query GroupingSubQuery Question

I am having trouble getting my head around this query for some reason and I was wondering if someone would be able to help me out here. I have the following 3 tables:
opp_cstm:
id_c make_c time_followup_c lead_category_c lead_type_c
9 GMC 224 GM Internet Sales
e Buick 809 GM Internet Service
8 GMC 1559 Dealer Web Sales
2 Cadillac 10596 Dealer Web Service
3 Chevrolet 15595 GM Internet Sales
4 Chevrolet 905 GM Internet Service
opportunities:
id date_entered deleted
2 2010-07-16 16:46:21 0
3 2010-07-16 16:55:53 0
4 2010-07-16 19:30:12 0
8 2010-07-16 16:44:13 0
9 2010-07-16 16:39:17 0
e 2010-07-16 16:41:44 0
leads_objectives:
makes_carried resp_time_obj
GMC 18000
Ford 7200
Cobalt 43200
Chevrolet 18000
Buick 18000
Cadillac 7200
I am needing to get the following layout (this will obviously be grouped by date, LCat):
Date LCat LType #ofLds AvgResp #LdsRespOT %LdsRespOT #Lds!RespOT %Lds!RespOT
19-Jul GM Internet Sales 10 18 minutes 7 70% 3 30%
19-Jul GM Internet Service 20 20 minutes 10 50% 10 50%
19-Jul Handraiser Sales 10 45 minutes 5 50% 5 50%
20-Jul Dealer Web Sales 20 120 minutes 5 25% 15 75%
20-Jul Dealer Web Service 10 7 minutes 3 30% 7 70%
Explanation of each column I need:
Date: opportunities.date_entered = today (this needs to be on everything of course)
LCat: opp_cstm.lead_category
LType: opp_cstm.lead_type
#ofLds: this needs to be the Count of opportunities where deleted = "0" and Lead Category is not null
AvgResp: Avg. of timefollowup-C field in opportunities where Deleted = "0" and Lead Category is not null and and time_followup_c > 0 and not null
#LdsRespOT: Count of opportunities where Deleted = "0" AND Lead Category is not null AND time_followup_c is less than or equal to resp_time_obj AND make_c = makes_carried and time_followup_c > 0 and not null
%LdsRespOT: (#LdsRespOT / #ofLds)
#Lds!RespOT: (#ofLds - #LdsRespOT)
%Lds!RespOT: (#Lds!RespOT / #ofLds)
I am having a hard time getting my head around this query. I was wondering if someone on here could provide some assistance of some sort with this one? How would I write this query correctly?
I have tried several times but fail every time and I am getting frustrated! I know I am just missing some grouping of some kind or some kind of sql subquery that I am missing.
Any help would be greatly appreciated!
Thanks!
For anyone who comes across this that might need help with something like this, here is what I ended up doing:
SELECT
opportunities.date_entered as Date,
opportunities_cstm.lead_category_c as LCat,
opportunities_cstm.lead_type_c as LType,
count(opportunities.id) as '# of Lds',
SUM(opportunities_cstm.time_followup_c)/count(opportunities.id) as AvgResp,
SUM(
CASE
WHEN (
opportunities_cstm.time_followup_c IS NOT NULL
AND
opportunities_cstm.time_followup_c < leads_handling_objectives.resp_time_obj
)
THEN
1
ELSE
0
END
) as '#LdsRespOT',
(SUM(
CASE
WHEN (
opportunities_cstm.time_followup_c IS NOT NULL
AND
opportunities_cstm.time_followup_c < leads_handling_objectives.resp_time_obj
)
THEN
1
ELSE
0
END
) /count(opportunities.id))*100 as '%LdsRespOT',
count(opportunities.id) - SUM(
CASE
WHEN (
opportunities_cstm.time_followup_c IS NOT NULL
AND
opportunities_cstm.time_followup_c < leads_handling_objectives.resp_time_obj
)
THEN
1
ELSE
0
END
)as '#Lds!RespOT',
((count(opportunities.id) - SUM(
CASE
WHEN (
opportunities_cstm.time_followup_c IS NOT NULL
AND
opportunities_cstm.time_followup_c < leads_handling_objectives.resp_time_obj
)
THEN
1
ELSE
0
END
))/count(opportunities.id))*100 as '%Lds!RespOT'
FROM
opportunities
INNER JOIN
opportunities_cstm
ON
opportunities_cstm.id_c = opportunities.id
AND
opportunities_cstm.lead_category_c IS NOT NULL
AND
opportunities_cstm.lead_category_c NOT LIKE ''
INNER JOIN
leads_handling_objectives
ON
leads_handling_objectives.makes_carried = opportunities_cstm.make_c
WHERE
opportunities.date_entered = DATE(NOW())
AND
opportunities.deleted='0'
GROUP BY
opportunities_cstm.lead_category_c