Access 2013 calculated field too complex - ms-access

Apparently, calculated field is way to complex. Could anyone suggest a better way to accomplish what I'm trying to do?
Goal: The value entered in the Strength Field determines that value that appears in the calculated field. Thanks in advance for any help!
[Strength] number field
[StrMod] Calculated field
Below is the expression I tried to build to support the [StrMod] calculated field.
IIf([Strength]=1,-5,
IIf([Strength]>=2 And [Strength]<=3,-4,
IIf([Strength]>=4 And [Strength]<=5,-3,
IIf([Strength]>=6 And [Strength]<=7,-2,
IIf([Strength]>=8 And [Strength]<=9,-1,
IIf([Strength]>=10 And [Strength]<=11,0,
IIf([Strength]>=12 And [Strength]<=13,1,
IIf([Strength]>=14 And [Strength]<=15,2,
IIf([Strength]>=16 And [Strength]<=17,3,
IIf([Strength]>=18 And [Strength]<=19,4,
IIf([Strength]>=20 And [Strength]<=21,5,
IIf([Strength]>=22 And [Strength]<=23,6,
IIf([Strength]>=24 And [Strength]<=25,7,
IIf([Strength]>=26 And [Strength]<=27,8,
IIf([Strength]>=28 And [Strength]<=29,9,
IIf([Strength]=30,10,Null)

Here are a few suggestions all using a non-calculated data field type.
UPDATE QUERY w/ LOOKUP TABLE
Replace the calculated field type to regular number field for [StrMod]. Create a Strength lookup table:
StrengthValue | StrengthCategory
1 -5
2 -4
3 -4
4 -3
5 -3
6 -2
... ...
Then use this table to create the below update query to be run in the AfterUpdate and AfterInsert data macros for main table or same events in main table's form.
UPDATE maintableName INNER JOIN StrengthLookUp
ON maintableName.Strength = StrengthLookup.StrengthValue
SET maintableName.StrMod = StrengthLookUp.StrengthCategory
UPDATE QUERY w/o LOOKUP TABLE
Replace the calculated field type to regular number field for [StrMod] and simply use an update query in AfterUpdate and AfterEvent events:
UPDATE maintableName
SET maintableName.StrMod =
IIf([Strength]=1,-5,
IIf([Strength]>=2 And [Strength]<=3,-4,
IIf([Strength]>=4 And [Strength]<=5,-3,
IIf([Strength]>=6 And [Strength]<=7,-2,
IIf([Strength]>=8 And [Strength]<=9,-1,
IIf([Strength]>=10 And [Strength]<=11,0,
IIf([Strength]>=12 And [Strength]<=13,1,
IIf([Strength]>=14 And [Strength]<=15,2,
IIf([Strength]>=16 And [Strength]<=17,3,
IIf([Strength]>=18 And [Strength]<=19,4,
IIf([Strength]>=20 And [Strength]<=21,5,
IIf([Strength]>=22 And [Strength]<=23,6,
IIf([Strength]>=24 And [Strength]<=25,7,
IIf([Strength]>=26 And [Strength]<=27,8,
IIf([Strength]>=28 And [Strength]<=29,9,
IIf([Strength]=30,10,Null))))))))))))))))
VBA LOGIC
Replace the calculated field type to regular number field for [StrMod]. Then, use the SELECT CASE statement in the main table's form's AfterInsert and AfterUpdate events:
SELECT CASE Me.Strength
Case 1
Me.StrMod = -5
Case 2 To 3
Me.StrMod = -4
Case 4 To 5
Me.StrMod = -3
Case 6 To 7
Me.StrMod = -3
Case 8 To 9
Me.StrMod = -1
Case 10 To 11
Me.StrMod = 0
Case 12 To 13
Me.StrMod = 1
...
END SELECT
Strictly my preference, but I never work with calculated fields in case of database compatibility (i.e., MS Access 2007 accdb users) and upsizing scalability with programming languages (PHP, Python, VB ODBC connections) and other RDMS (SQL Server, MySQL).

I can not check but you will get the idea:
iif(strength/2 >= 15, null, -5 + INT(strength/2))
Did you want to simplify or complicate? If you want just to update your table once then you don't need any lookup tables...
update table
set StrMode = iif(strength/2 >= 15, null, -5 + INT(strength/2))
But if records are added to table from time to time you will need to run update as well.

Related

Get value between from to dataset columns ssrs

I have a data set like that:
Data Set Contents
From To Comment
----+---+--------
0 50 Bad
50 70 Good
70 100 Excellent
If I have a value of 75, I need to get Excellent by searching the Dataset.
I know about the lookup function but it is not what I want. How can I do that?
The values should be in percentage.
Note : the value (75) is Average of a column (Calculated) it
calculate student grade from max and student mark Version SQL Server
2016
Note 2 : the dataset is from database not static values
Thank You
Assuming you only ever have a fixed number of 'grades' then this will work. However, I would strongly recommend doing this type of work on the server where possible.
Here we go...
I created two datasets
dsGradeRange with the following sql to recreate your example (more or less)
DECLARE #t TABLE (low int, high int, comment varchar(20))
INSERT INTO #t VALUES
(0,49,'Bad'),
(50,69,'Good'),
(70,100, 'Excellent')
SELECT * FROM #t
dsRandomNumbers This just creates 30 random numbers between 0 and 100
SELECT *
FROM (SELECT top 30 ABS(CHECKSUM(NEWID()) % 100) as myNumber FROM sys.objects) x
ORDER BY myNumber
I added a table to the report to show the grades (just for reference).
I then added a table to show the dsRandomNumbers
Finally I set the expression of the 2nd column to the following expression.
=SWITCH
(
Fields!myNumber.Value < LOOKUP("Bad", Fields!comment.Value, Fields!high.Value, "dsGradeRange"), "Bad",
Fields!myNumber.Value < LOOKUP("Good", Fields!comment.Value, Fields!high.Value, "dsGradeRange"), "Good",
True, "Excellent"
)
This gives the following results
As you can see we only need to compare to the high value of each case, the first match will return the correct comment.
Right click on your dataset and add a calculated field. Go to Field Properties > Fields > Add and add the following expression, which descripes your scenario:
=IIF(Fields!Number.Value < 50, "Bad", "Good")

Add Column in Table with conditional in block WHERE

I was doing a query with MySQL to save all objects returned, but I'd like identify these objects based in statements of the block WHERE, that is, if determined object to satisfy the specific characteristic I'd like create one column and in this column I assignment the value 0 or 1 in the row corresponding the object if it satisfy or not satisfy these characteristic.
This is my script:
SELECT
s.id, al.ID, al.j, al.k, al.r, gal.i
FROM
datas as al
WHERE
AND s.id = al.ID
AND al.j between 1 and 1
AND al.k BETWEEN 15 and 16
AND al.r BETWEEN 67 and 72
The script above is working perfectly and I can to save all objects which it return.
So, I'd like to know if is there a way add in the query above, on block WHERE, the following statement,
( Flags & (dbo.environment('cool') +
dbo.environment('ok') -
dbo.environment('source')) ) = 25
and ((al_pp x al_pp1)-0.5/3=11
and determined the objects that satisfy or not these condition with 0 or 1 in a new column created in Table saved.
I read some tutorials about this and saw some attempts with IF, CASE, ADD COLUMN or WHEN, but none of these solved.
Thanks in advance
MySQL has if function, see here
So you can simply use it in your query:
SELECT IF(( Flags & (dbo.fPhotoFlags('SATURATED') +
dbo.fPhotoFlags('BRIGHT') +
dbo.fPhotoFlags('EDGE')) ) = 0
and petroRad_r < 18
and ((colc_u - colc_g) - (psfMag_u - psfMag_g)) < -0.4
, 1 --// VALUE IF TRUE
, 0 --// VALUE IF FALSE
) as conditional_column, ... rest of your query

How to put Multiple checks in Expression Builder in a MS Access Form?

I am working on a macro in MS-Access which does some check on different Values in Form.
Here are the details of what i'm trying to do:
Form : Form is created based on a Table present in database and the structure of the same is like
DataType CalcType Percent1 Percent2 Percent3 percent_check
DT1 Avg 20 30 50 100
DT2 Mean 30 33 35 98
DT3 Sum 10 35 57 102
Column CalcType is a dropdown with three options. Each option would invoke different Macro written for it's calculation.
I have added a separate Field percent_check to validate the sum of P1, P2 & P3.
Requirement:
I want to write a condition that
IF DataType is DT1
THEN IF percent_check<=100
THEN IF CalcType = "Avg" Invoke Avg_Macro
ELSE IF CalcType = "Mean" Invoke Mean_Macro
ELSE Invoke Sum_Macro
ELSE Message(Adjust the percent to make total as 100)
similarly for the rest of the data types.
I have written the cases in Expression Builder
IF Form!DataType = DT1 THEN
IF Form!percent_check <=100 THEN
IF Form!CalcType = Avg THEN RunMacro - Avg_Macro
ELSE IF Form!CalcType = Mean THEN RunMacro - Mean_Macro
ELSE RunMacro - Sum_Macro
ELSE MessageBox("Adjust percent to make total <=100)
But i am neither getting any results nor any error message.
Could anyone please help me in writing this expression for getting the required results.
Thanks!!
Use VBA and rewrite the macro's into VBA too.

MS Access Calc Field with combined fields

I have been trying to resolve this calc field issue for about 30 mins, it looks like I have the single field conditions correct in the expression such as [points] and [contrib] but the combined ([points]+[contrib]) field is not meeting the requirement that sets the field to the correct member type, so when these are added it returns some other member type as basic. Might I use the between operator with the added fields...? I tried it, but there is some compositional error. So in other words if you got 45 points it sets you to basic only named in the points field, if you have contrib of 45 you are set to basic in the calc field as expected, but if it were 50 + 50, instead it is setting to basic when it should be "better" member label. Otherwise this simple statement should seem to be correct but the computer is not reading it so when adding. It must not be recognizing the combined value for some reason and calc fields do not have a sum() func.
Focus here: (([points]+[Contrib]) >= 45 And ([points]+[Contrib]) < 100),"Basic",
IIf(([points] >=45 And [points]<100) Or ([Contrib] >=45 And [Contrib] <100) Or (([points]+[Contrib]) > = 45 And ([points]+[contrib] < 100),"Basic",
IIf(([points] >=100 And [points] <250) Or ([Contrib] >=100 And [Contrib] <250) Or ((([points]+[Contrib]) >=100) And (([points]+[Contrib])<250)),"Better",
IIf(([points] >=250 And [points]<500) Or ([Contrib] >=250 And [Contrib] <500) Or ((([points]+[Contrib]) >=250) And (([points]+[Contrib])<500)),"Great",
IIf(([points] >=500) Or ([Contrib] >=500) Or (([points]+[Contrib]) >=500),"Best","Non-member"))))
Here is a data sample from an Access 2010 table which includes a calculated field named member_type:
id points Contrib member_type
-- ------ ------- ----------
1 1 1 Non-member
2 50 1 Basic
3 200 1 Better
4 300 1 Great
5 600 1 Best
If that is what you want for your calculated field, here is the expression I used for member_type:
IIf([points]+[Contrib]>=45 And [points]+[Contrib]<100,'Basic',IIf([points]+[Contrib]>=100 And [points]+[Contrib]<250,'Better',IIf([points]+[Contrib]>=250 And [points]+[Contrib]<500,'Great',IIf([points]+[Contrib]>=500,'Best','Non-member'))))
In case I didn't get it exactly correct, here is that same expression formatted so that you can better see where you need changes:
IIf([points]+[Contrib]>=45 And [points]+[Contrib]<100,'Basic',
IIf([points]+[Contrib]>=100 And [points]+[Contrib]<250,'Better',
IIf([points]+[Contrib]>=250 And [points]+[Contrib]<500,'Great',
IIf([points]+[Contrib]>=500,'Best','Non-member'
))))
Note if either points or Contrib is Null, member_type will display "Non-member". If that is not the behavior you want, you will need a more complicated expression. Since a calculated field expression can not use Nz(), you would have to substitute something like IIf([points] Is Null,0,[points]) for every occurrence of [points] and IIf([Contrib] Is Null,0,[Contrib]) for [Contrib]
It would be simpler to prohibit Null for those fields (set their Required property to Yes) and set Default Value to zero.
The BETWEEN operator returns TRUE if the value you are testing is >= or <= the limits you have for BETWEEN.
If you are looking at 50+50 then that total = 100 and you are Between 44 and 100. That would result in an answer of "Basic". Change the range for ([points]+[Contrib]) Between 44 And 100) to be ([points]+[Contrib]) Between 44 And 99)

MySQL - get all column averages also with a 'total' average

I have a MySQL table which looks like this:
id load_transit load_standby
1 40 20
2 30 15
3 50 10
I need to do the following calculations:
load_transit_mean = (40+30+50)/3 = 40
load_standby_mean = (20+15+10)/3 = 15
total_mean = (40+15)/2 = 27.5
Is it possible to do this in a single query? What would the best design be?
I need my answer to be scalable (the real design has more rows and columns), and able to handle some rows containing NULL.
I believe this would do it:
SELECT AVG(Load_transit)
, AVG(load_standby)
, (AVG(Load_transit) + AVG(load_standby))/2.0
FROM table
The AVG() function handles NULL's in that it ignores them, if you want the NULL row to be counted in your denominator you can replace AVG() with SUM() over COUNT(*), ie:
SUM(load_transit)/COUNT(*)
Regarding scalability, manually listing them out like above is probably the simplest solution.