I have a report I am building that I am summing a column with the total minutes listed in it then dividing it by 60 to get number of hours like so.
=Sum(Fields!designtimeValue.Value) / 60
But I have a condition where I want to weed out rows that contain other data in another column
Its laid out like so
Submittal_date Submittal_returned Design_Hours
12/01/2014 180
12/01/2014 12/02/2014 240
12/01/2014 60
So I want to do something like =Sum(IIF(Fields!sumbittal_returned.Value="NULL",Fields!design_hours.Value)) / 60
But it is throwing an error the sum iff does not allow that number of exceptions
I then need to take it a step further And be able to take the sum of design total if submittal_returned = NULL total then for any instance submittal_returned = Not-NULL add 120 minutes
Thanks
Edit : format code
IIF takes 3 arguments. A condition, a true result, and a false result. You have to supply all three.
This would be the correct syntax:
=Sum(IIF(IsNothing(Fields!submittal_returned.Value),Fields!design_hours.Value,0)) / 60
Although that condition will only be true if submittal_returned actually contained the string "NULL". If it's actually NULL (not a string), you would need test with the IsNothing() function.
Not sure I understand your last sentence, maybe you mean this?:
=Sum(IIF(IsNothing(Fields!submittal_returned.Value),Fields!design_hours.Value,Fields!design_hours.Value + 120)) / 60
Related
I am trying to complete a mortality table, using loops in Visual Foxpro. I have run into one difficulty where the math operation involves doing a sum of of all data in a column for the remaining rows - this needs to be incorporated into a loop. The strategy I thought would work, nesting a SUM REST function into the SCAN REST function, was not successful, and I haven't found a good alternative approach.
In FoxPro, I can successfully use the SCAN function as follows, say:
Go 1
Replace survivors WITH 1000000
SCATTER NAME oprev
SKIP
SCAN rest
replace survivors WITH (1 - oprev.prob) * oprev.survivors
SCATTER NAME oprev
ENDSCAN
(to take the mortality rates in a table and use it to compute number of survivors at each age)
Or, say:
Replace Yearslived WITH 0
SCATTER NAME oprev1
SKIP
SCAN rest
replace Yearslived WITH (oprev1.survivors + survivors) * 0.5
SCATTER NAME oprev1
ENDSCAN
In order to complete a mortality table I want to use the Yearslived and survivors data (which were produced using the SCANs above) to get life expectancy data as follows. Say we have the simplified table:
SURVIVORS YEARSLIVED LIFEEXP
100 0 ?
80 90 ?
60 70 ?
40 50 ?
20 30 ?
0 10 ?
Then each LIFEEXP record should be the sum of the remaining YEARSLIVED records divided by the corresponding Survivors record, i.e:
LIFEEXP (1) = (90+70+50+30+10)/100
LIFEEXP (2) = (70+50+30+10)/80
...and so on.
I attempted to do this with a similar SCAN approach - see below:
Go 1
SCATTER NAME Oprev2
SCAN rest
replace lifeexp WITH ((SUM yearslived Rest) - oprev2.yearslived) / oprev2.survivors
SCATTER NAME oprev2
ENDSCAN
But here I get the error message "Function name is missing)." Help tells me this is probably because the function contains too many arguments.
So I then also tried to break things down and first use SCAN just to get all of my SUM REST data, as follows:
SCAN rest
SUM yearslived REST
END SCAN
... in the hope that I could get this data, define it as a variable, and create a simpler SCAN function above. However, I seem to be doing something wrong here as well, as instead of getting all necessary sums (first the sum of rows 2 to end, then 3 to end, etc.), I only get one sum, of all the yearslived data. In other words, using the sample data, I am given just 250, instead of the list 250, 160, 90, 40, 10.
What am I doing wrong? And more generally, how can I create a loop in Foxpro that includes a function where you Sum up all remaining data in a specific column over and over again (first 2nd through last record, then 3rd through last record, and so on)?
Any help will be much appreciated!
TM
Well you are really hiding the important detail, your table's structure, sample data and desired output. Then it is mostly guess work which have a high chance of to be true.
You seem to be trying to do something like this:
Create Cursor Mortality (Survivors i, YearsLived i, LifeExp b)
Local ix, oprev1
For ix=100 To 0 Step -20
Insert Into Mortality (Survivors, YearsLived) Values (m.ix,0)
Endfor
Locate
Survivors = Mortality.Survivors
Skip
Scan Rest
Replace YearsLived With (m.Survivors + Mortality.Survivors) * 0.5
Survivors = Mortality.Survivors
Endscan
*** Here is the part that deals with your sum problem
Local nRecNo, nSum
Scan
* Save current recnord number
nRecNo = Recno()
Skip
* Sum REST after skipping to next row
Sum YearsLived Rest To nSum
* Position back to row where we started
Go m.nRecNo
* Do the replacement
Replace LifeExp With Iif(Survivors=0,0,m.nSum/Survivors)
* ENDSCAN would implicitly move to next record
Endscan
* We are done. Go first record and browse
Locate
Browse
While there are N ways to do this in VFP, this is one xbase approach to do that and relatively simple to understand IMHO.
Where did you go wrong?
Well, you tried to use SUM as if it were a function, but it is a command. There is SUM() function for SQL as an aggregate function but here you are using the xBase command SUM.
EDIT: And BTW in this code:
SCAN rest
SUM yearslived REST
ENDSCAN
What you are doing is, starting a SCAN with a scope of REST, in loop you are using another scoped command
SUM yearslived REST
This effectively does the summing on the REST of records and places the record pointer to bottom. Endscan further advances it to eof(). Thus it only works for the first record.
I'm trying to calculate a row value based on the previous row value in the same column within a report expression. I can't precalculate this from database since starting point of calculation is dependent from input parameters and values in a table should be recalculated dynamically within report itself.
In Excel analogical data and formula look like as it is shown below (starting point is always 100):
B C D E
Price PreviousPrice CalcValue Formula
1 NULL NULL 100
2 2.6 2.5 104 B2/C2*D1
3 2.55 2.6 102 B3/C3*D2
4 2.6 2.55 104 B4/C4*D3
5 2.625 2.6 105 B5/C5*D4
6 2.65 2.625 106 B6/C6*D5
7 2.675 2.65 107 B7/C7*D6
I tried to calculate expected values ("CalcValue" is the name of column where expression is set) like this:
=Fields!Price.Value/ PreviousPrice.Value * Previous(reportitems("CalcValue").Value))
but got an error "Aggregate functions can be used only on report items contained in page headers and footers"
Can you please advice whether expected result is achievable in my case and suggest a solution?
Thank you in advance!
Sadly I'm still facing with issue: calculated column does not consider previous calculated value. E.g., I added CalcVal field with 100 as default and tried to calculate using above approach, like: =previous(runningValue(Fields!CalcVal.Value, sum, "DataSet1") ) * Fields!Price.Value/Fields!PreviousPrice.Value.
But in this case it always multiples Fields!Price.Value/Fields!PreviousPrice.Value by 100..
For example CalcVal on Fly always show 200
=previous(runningValue(Fields!CalcVal.Value, sum, "DataSet1")) * 2
https://imgur.com/Wtg3Wsg
I tried with your sample data, here is how I achieved the results
Formula to use, You might have to take care of null values
=Fields!Price.Value/(Fields!PreviousPrice.Value*Previous(Fields!CalcValue.Value))
Edit: Update to answer after Op's comment
CalcValue is caluated with below formula i.e on the fly
=RunningValue(CountDistinct("Tablix6"),Count,"Tablix6"*100
and then Final value as below
=Fields!Price.Value/(Fields!PreviousPrice.Value*
Previous(RunningValue(CountDistinct("Tablix6"),Count,"Tablix6"))*100)
I have a report that in part is providing: Job Date, Job Target Date and Completion date.
I have a column at the end that works out whether or not the job was completed within the target time our outside of returning true or false.
As mentioned, I have created a column to work out whether a job is completed on time and I have tried googling many different solutions and trying them out.
The expression I've used to work out whether the job was completed on time is:
=IIF(Fields!CompletedDate.Value <= Fields!Target.Value, "True", "False")
Now I need an expression to work out the percentage that are within the target. So, let's say there are 80 jobs and 67 are completed in time. It would be 'True' (67) / 80 *100 = 83%.
The expression I've used to work out whether the job was completed on time is:
=IIF(Fields!CompletedDate.Value <= Fields!Target.Value, "True", "False")
Now I need an expression to work out the percentage that are within the target. So, let's say there are 80 jobs and 67 are completed in time. It would be 'True' (67) / 80 *100 = 83%.
I figured this one out myself, again..
If anyone is interested I kept the same IF statement in the original cell. I then created 2 additional cells underneath one containing the text 'Percentage of jobs completed on target' and the other cell I added a new expression that included the original one above;
=SUM(IIF(Fields!CompletedDate.Value <= Fields!Target.Value, 1, 0)) / count(Fields!PropertyCode.Value)
All I had to keep in mind was that I am already showing the results as true and false so in my seconds expression I change the values to numbers so I can calculate. True is '1' so I know that it will not be calculating on 0 as it cannot divide by zero.
So, I did a sum on the number true represented as 1 divided by number of results. Rather than times this by 100 ( 5/19*100 = percentage), I simply left out the times and changed the format of that cell to percentage so it takes the value in the cell and returns the percentage.
Thanks,
Jordan
I'm doing a division for each record and updating a certain column with the result
so my sql looks something like this
update table1 set frequency = num/denom where id>XXX
my frequency data type is number(10,10)
Based on https://docs.oracle.com/cd/B28359_01/server.111/b28318/datatype.htm#CNCPT1838
First, I'm not even sure why I get this data because the answer will always be 0.XXX, so giving 10 before the comma would be a plenty. Then the 10 after the comma should be okay too because it will truncate if the answer is bigger.
NUMBER(10, 10) means 10 digits and a scale of 10.
That means you have 10 digits right of the decimal point which means no digit left of it.
So having the table
CREATE TABLE t
(
test NUMBER (10, 10)
);
insert into t values (0.9999999999); will work, while
insert into t values (0.99999999999);will fail because the value is rounded up to 1.
So if num/denom is 1 or even larger you will get ORA-01438: value larger than specified precision allowed for this column.
But you will also get this error, if num/denom is larger then 0.99999999995 as oracle tries to round it to 1.
First of all, let me get this confusion around the precision and scale cleared out. According to the documentation, it is stated:
For numeric columns, you can specify the column as:
column_name NUMBER
Optionally, you can also specify a precision
(total number of digits) and scale (number of digits to the right of
the decimal point):
column_name NUMBER (precision, scale)
In your case:
frequency NUMBER(10,10)
This means, that the total number of digits is 10 and this means that the column can accommodate values from:
0.0000000001
to:
9999999999
This includes Integers up to 9999999999 (10 nines) and floats from 0.0000000001 (9 zeroes and a 1 at the end).
Now that we know this, let's proceed to the problem..
You need this query to never fail with ORA-01438:
update table1 set frequency = num/denom where id>XXX;
You can do the following check, on update time:
update table1
set frequency = CASE LENGTH(TRUNC(num/denom)) >=10
THEN TRUNC(num/denom, 10)
ELSE
ROUND(num/denom), 10 - LENGTH(TRUNC(num/denom))) --TRUNC
END
where id>XXX;
What this would do is check:
1. If the whole part of the division is more than or equal to 10; in that case, return only the first 10 digits (TRUNCATE).
2. If the whole part is less than 10; in that case ROUND the result to "10 - LENGTH_OF_WHOLE_PART" decimal places, but still within the precision of 10, which is the one of the column.
*Note: The ROUND above will actually ROUND the result, giving you an inaccurate value. If you need to get a raw truncation of the result, use TRUNCATE instead of ROUND above!
Cheers
I am a beginner in prolog and was wondering if there was an easy way to convert numbers to time, for comparison.
For example:
The below two lists show bus name, capacity, time it arrives at city, time it departs city.
bus_info(bus1,150, 12:30, 14:30).
bus_info(bus2, 200, 16:00, 18:00).
passenger_info(mike, 21, 17:30). -shows name, age, and time available
I want to check which bus Mike can catch. The answer is bus 2, but how do I calculate this in prolog?
You're just comparing times for a given day so you don't need to convert the numbers to any kind of system time encoding. You only need, say "minutes past midnight" or something like that. For example, 12:30 would be (12*60)+30 minutes past midnight. And you can use that as your comparison units for a daily schedule.
To capture your hours and minutes to do this calculation, if you were to "ask" in Prolog:
bus_info(Bus, Num, StartHH:StartMM, EndHH:EndMM).
You would get two results:
Bus = bus1
Num = 150
StartHH = 12
StartMM = 30
EndHH = 14
EndHH = 30
And
Bus = bus2
Num = 200
StartHH = 16
StartMM = 0
EndHH = 18
EndMM = 0
To assign a numeric value of an expression in Prolog, you need the is predicate. For example:
StartTime is (StartHH * 60) + StartMM.
That basic information should get you started if you've learned how Prolog predicates basically work.