Why is this IIF function giving an #Error? - ms-access

One of my tables has a field named Cost and a field named Extra Cost. To come up with the Total Cost, I add them together with the following field, which works just fine:
Total Cost: (Val(nz([Cost],"")))/100 + (Val(nz([Extra Cost],"")))/100
(I divide by 100 because Cost and Extra Cost are stored without a decimal point)
Now it's possible that a record will have Cost = 0, and Extra Cost > 0. But if Cost = 0, I want Total Cost to also = 0. I came up with the following, but it results in #Error if Cost = 0. It works fine if Cost > 0:
Total Cost: IIf([Cost]>0,((Val(nz([Cost],"")))/100+(Val(nz([Extra Cost],""))))/100,0)
Basically I'm looking for:
If Cost = 0, Then Total Cost = 0
Else
If Cost > 0, Then Total Cost = Cost + Extra Cost
What is wrong with the 'true' portion?
Here's a few examples of the data:
Cost Extra Cost
100 2.5
250 1.5
150 2.5
null 2.75

Based on your description, I think you can divide by 100 after you add the 2 values instead of dividing each of them by 100 before you add them. That shouldn't affect the logic, but should give you a simpler IIf expression ... which will hopefully be easier to diagnose.
IIf
(
Val(Nz([Cost], "0")) > 0,
(Val([Cost]) + Val(Nz([Extra Cost], "0"))) / 100,
0
)
Using your sample data in Access 2007, I get this result set from the following query:
Cost Extra Cost Total Cost
100 2.5 1.025
250 1.5 2.515
150 2.5 1.525
2.75 0
SELECT
y.Cost,
y.[Extra Cost],
IIf
(
Val(Nz([Cost], "0")) > 0,
(Val([Cost]) + Val(Nz([Extra Cost], "0"))) / 100,
0
) AS [Total Cost]
FROM YourTable AS y;
If the issue is that [Total Cost] requires a text value, you can use CStr() to cast the IIf numerical value to string.
CStr(
IIf
(
Val(Nz([Cost], "0")) > 0,
(Val([Cost]) + Val(Nz([Extra Cost], "0"))) / 100,
0
)
)

Related

MySQL CASE statement returning null

I have two 'identical' operations
(1)
SELECT ticket_type_name
, amount as 'original_amount'
, CASE ticket_type_name
WHEN ticket_type_name = 'General Admission - Friday'
and amount > 0 THEN amount / 400
END AS 'NewAmount'
from analytics.deleteme
(2)
select distinct ticket_type_name, amount, amount/400 AS NewAmount
from analytics.deleteme
where amount > 0
and ticket_type_name = 'General Admission - Friday'
The first statement generates a value of NULL
The second statement generates a correct value of 1 (400/400)
I have added an ELSE statement at the end:
SELECT DISTINCT ticket_type_name
, amount as 'original_amount'
, CASE ticket_type_name
WHEN ticket_type_name = 'General Admission - Friday' and amount > 0 THEN amount / 400
else amount/575
END AS 'NewAmount'
from analytics.deleteme
where amount > 0
Results are the reverse of what they should be!
GA Friday should be 400/400 = 1
Everything else, eg GA Weekend should be divided by 575 (=0.82, not 1.18!)
ticket_type_name, amount, NewAmount
General Admission - Friday 400.0 0.69
General Admission - Weekend 475.0 1.18
General Admission - Saturday 375.0 0.93
Children (12 to 14 Years) - Weekend 100.0 0.25
Children (12 to 14 Years) - Saturday 50.0 0.125
I could replicate your bug.
Just remove ticket_type_name after CASE and it works:
SELECT
DISTINCT ticket_type_name,
amount AS 'original_amount',
CASE
WHEN
ticket_type_name = 'General Admission - Friday'
AND amount > 0
THEN
amount / 400
ELSE
amount / 575
END AS 'NewAmount'
FROM analytics.deleteme
WHERE amount > 0;
You don't need to put anything between CASE and WHEN but it's funny how this broke the query. The first comment below perfectly explains why.
As an alternative, you may move ticket_type_name after CASE and put the comparison value after WHEN. Like this:
SELECT
DISTINCT ticket_type_name,
amount AS 'original_amount',
CASE ticket_type_name
WHEN
'General Admission - Friday'
THEN
amount / 400
ELSE
amount / 575
END AS 'NewAmount'
FROM analytics.deleteme
WHERE amount > 0;
Long story short: either use CASE field WHEN value… or CASE WHEN condition…. You don't want to use CASE field WHEN condition….

Calculate sum when value changes

I am trying to build a system that will track vehicle fuelings, and have run into a problem with one report; determining fuel efficiency in distance/fuel. Sample data is:
odometer
fuel
partial_fillup
61290
10.3370
0
61542
6.4300
0
61735
4.3600
0
61994
7.5000
0
62242
5.4070
0
62452
8.1100
0
62713
5.7410
1
62876
9.4850
0
63243
6.1370
1
63499
10.7660
0
Where odometer is the total distance the vehicle has traveled, fuel is the number of gallons or liters put in, and partial_fillup is a boolean meaning the fuel tank was not completely filled if non-zero.
If the user fills the tank each time the query I can use is:
set #a = null;
select
odometer,
odometer-previousOdometer distance,
fuel,
(odometer-previousOdometer)/fuel mpg,
partial_fillup
from
(
select
#a as previousOdometer,
#a:=odometer,
odometer,
fuel/1000 fuel,
partial_fillup
from fuel
where
vehicle_id =1
and odometer >= 61290
order by odometer
) as readings
where readings.previousOdometer is not null;
However, when the user only partially fills the tank, the correct procedure would be to subtract the last full fueling from current odometer reading, then divide by the sum of all fuel since the previous odometer reading, so at odometer 63499, the calculate would be (63499-62876)/(10.7660+6.1370)
This will get the average used on the last ride:
select
odometer,
odometer-lag(odometer) over (order by odometer) as distance,
fuel,
(odometer-lag(odometer) over (order by odometer))/fuel as mpg
from fuel
output:
odometer
distance
fuel
mpg
61290
10.3370
61542
252
6.4300
39.1913
61735
193
4.3600
44.2661
61994
259
7.5000
34.5333
62242
248
5.4070
45.8665
62452
210
8.1100
25.8940
62713
261
5.7410
45.4625
62876
163
9.4850
17.1850
63243
367
6.1370
59.8012
63499
256
10.7660
23.7786
Or you can calculate the total drive distance, and the total amount of fuel used:
select
distance,
sum_fuel,
distance/sum_fuel as mpg
from (
select
f.odometer,
f.odometer-(select min(odometer) from fuel) as distance,
fuel,
sum_fuel
from fuel f
inner join (
select
odometer,
sum(fuel) over (order by R) as sum_fuel
from (
select
odometer,
fuel,
row_number() over (order by odometer) R
from fuel) x
) x on x.odometer = f.odometer
) x2
which will get next output, which will get closer to an average after a longer time of measurement:
distance
sum_fuel
mpg
0
10.3370
0.0000
252
16.7670
15.0295
445
21.1270
21.0631
704
28.6270
24.5922
952
34.0340
27.9720
1162
42.1440
27.5721
1423
47.8850
29.7170
1586
57.3700
27.6451
1953
63.5070
30.7525
2209
74.2730
29.7416
DBFIDDLE
I was able to figure it out after studying Luuk's answer. I'm sure there is a more efficient way to do this; I am not used to using variables in SQL. But, the answers are correct in the test data.
set #oldOdometer = null;
set #totalFuel = 0;
select
s.odometer,
format(fuel, 3) fuel,
s.distance,
format( distance / fuel, 2) as mpg
from (
select
partial_fillup as partial,
odometer,
(fuel+#totalFuel) as fuel,
#totalFuel as totalFuel,
#oldOdometer oldOdometer,
if ( partial_fillup, null,odometer - #oldOdometer ) as distance,
#totalFuel := if ( partial_fillup, #totalFuel + fuel, 0) as pastFuel,
#oldOdometer := if (partial_fillup,#oldOdometer,odometer ) as runningOdometer
from
fuel
order by
odometer ) s
where s.distance is not null
order by s.odometer
limit 1,999;
limit 1,999 simply there to skip the first row returned, since there is not enough data to calculate distance or mpg. On my copy of MySQL, doing this means you do not need to initialize the two variables (you don't have to include the set commands at the beginning), so it works with my reporting tool very well. If you do initialize them, you do not need the limit statement. Works assuming you don't have more than 999 rows returned.

Grafana mysql query

Please suggest the MySQL queries for grafana.
I have data with I required MTTR from data, I'm getting expected output with add "15" as an integer in the query but not with count queries.
from "[with integer][1]" image.
sum(seconds_to_resolve) / 15 /60 as "MTTR" ---> value is 25.4
Getting different value if mentioned
from "[with count Function][2]" image.
sum(seconds_to_resolve) / count(seconds_to_resolve) / 60 as "MTTR" ---> value is 322
query:
SELECT
$__timeGroupAlias(created_on,$__interval),
sum(seconds_to_first_ack) AS "seconds_to_first_ack",
sum(seconds_to_resolve) AS "seconds_to_first_resolve",
count(seconds_to_resolve) AS "COUNT",
sum(seconds_to_resolve) / count(seconds_to_resolve) /60 as "MTTR"
FROM alerts_report
WHERE
$__timeFilter(created_on) AND
service_name = 'RKSOL'
GROUP BY 1
ORDER BY $__timeGroup(created_on,$__interval)
[with integer]
[with count Function]
I would use average function to calculate MTTR (mean time to resolution):
SELECT
$__timeGroupAlias(created_on,$__interval),
sum(seconds_to_first_ack) AS "seconds_to_first_ack",
sum(seconds_to_resolve) AS "seconds_to_first_resolve",
count(seconds_to_resolve) AS "COUNT",
avg(seconds_to_resolve) AS "MTTR"
FROM alerts_report
WHERE
$__timeFilter(created_on) AND
service_name = 'RKSOL'
GROUP BY 1
ORDER BY $__timeGroup(created_on,$__interval)

How to convert set to single value for rows in MDX Query?

I have following query that is producing the output as shown in the picture.
WITH
SET ConsignmentYear as
(
[Period].[YearAndMonth].[ConsignmentMonth].ALLMEMBERS
*[Period].[YearAndQuarter[ConsignmentYear].ALLMEMBERS
)
SELECT
NON EMPTY
{
[Measures].[Amount]
, [Measures].[LDM]
, [Measures].[Weight]
, [Measures].[CBM]
} ON COLUMNS,
NON EMPTY
{ (ConsignmentYear) }ON ROWS
FROM [RebellOlap]
While I need sets on Row dimension as date ( e.g 1-2014, 2-2014, 3-2014, 12-2014) instead of having a set containing two values separately.
Because, each row corresponds to a date
So I need finally
Year Amount LDM Weight CBM
1-2014----> 2.64 0 191.4 0
2-2014----> 2.64 0 191.4 0
4-2014----> 2.64 0 191.4 0
1-2015----> 2.64 0 191.4 0
...........................................
How can I achieve this?
I would use a measure:
WITH
MEMBER [Measures].[concatenated] AS
[Date].[Month of Year].CurrentMember.Member_Caption + ' - '
+
[Date].[Calendar Year].CurrentMember.Member_Caption
SELECT
{[Measures].[concatenated]} ON 0
,
[Date].[Month of Year].[Month of Year]*
[Date].[Calendar Year].[Calendar Year] ON 1
FROM [Adventure Works];
Result of above:
Or change your date dimension so that the concatenated date is a hierarchy of its own within the date dimension

MySQL - how to compute incremental charges?

Assume a service is billed in the following manner:
The first 60 seconds is charged at $1.00
Subsequent charges are billed at $0.25 per 10 second
The following are example computations:
32 seconds = $1.00
59 seconds = $1.00
60 seconds = $1.00
61 seconds = $1.25
69 seconds = $1.25
70 seconds = $1.25
71 seconds = $1.50
Is it possible to do this kind of computation in MySQL alone?
EDIT 1:
Does something like this work:
SELECT `call_length`,
( 1.00 + ( Round(( `call_length` - 30 ) / 10) * .25 ) ) AS `cost`
FROM `service`
SqlFiddleDemo
CREATE TABLE sec(val INT);
INSERT INTO sec
VALUES (32), (59), (60), (61), (69), (70), (71);
SELECT
val,
1.0 + CASE
WHEN val <= 60.0 THEN 0
WHEN val MOD 10 = 0 THEN 0.25 *((val - 60) DIV 10)
ELSE 0.25 * (((val - 60) DIV 10) + 1)
END AS charge
FROM sec;
EDIT:
Without CASE:
SqlFiddleDemo2
SELECT
call_length,
1.0 + IF( call_length <= 60, 0, 0.25 * CEIL((call_length - 60)/10)) AS cost
FROM service;
This is not much of a MySQL problem, unless the setting in which you need to perform the calculation is somehow difficult(?).
UPDATE ... SET cost_cents = 100 + CEIL(GREATEST(0, duration - 60)/10) * 25;
As a SELECT to match your edit,
SELECT `call_length`,
100 + CEIL(GREATEST(0, `call_length` - 60)/10) * 25 AS `cost`
FROM `service`
Note that this returns cents. For dollars, divide the result by 100...
SELECT `call_length`,
(100 + CEIL(GREATEST(0, `call_length` - 60)/10) * 25) / 100 AS `cost`
FROM `service`