Reputation: 107
I have a column in MS Access that contains course grade information for students. I am trying to calculate a letter grade in another column based on the contents of the grade column.
Below is what I have so far:
IIf([Grade]>92.5,"A",
IIf([Grade]>89.5,IIf([Grade]<92.5,"A-",
IIf([Grade]>86.5,IIf([Grade]<89.5,"B+",
IIf([Grade]>82.5,IIf([Grade]<86.5,"B",
IIf([Grade]>79.5,IIf([Grade]<82.5,"B",
IIf([Grade]>69.5,IIf([Grade]<79.5,"C",
IIf([Grade]<69.5,"F"))))))))))))
This works as intended for "A" and "A-" but all the other course grades come out as blanks.
Here is the "A" and "A-" working alone:
IIf([Grade]>92.5,"A",IIf([Grade]>89.5,IIf([Grade]<92.5,"A-")))
Any help will be greatly appreciated.
Upvotes: 1
Views: 2089
Reputation: 107567
Your immediate issue is that in your nested IIF
, you placed the low end first and then the high end second. Simply reverse and you output all matching letters but miss out on 0.5 endpoints.
IIf([Grade]>92.5,"A",
IIf([Grade]<92.5, IIf([Grade]>89.5,"A-",
IIf([Grade]<89.5, IIf([Grade]>86.5,"B+",
IIf([Grade]<86.5, IIf([Grade]>82.5,"B",
IIf([Grade]<82.5, IIf([Grade]>79.5,"B-",
IIf([Grade]<79.5, IIf([Grade]>69.5,"C",
IIf([Grade]<69.5,"F")))))))))))) As Letter
Alternatively, with less IIF
use BETWEEN
or > AND <
. And since BETWEEN
includes both end points and to be exhaustive, consider adding .49999999
.
IIf([Grade]>92.5,"A",
IIf([Grade] BETWEEN 89.5 AND 92.49999999,"A-",
IIf([Grade] BETWEEN 86.5 AND 89.49999999,"B+",
IIf([Grade] BETWEEN 82.5 AND 86.49999999,"B",
IIf([Grade] BETWEEN 79.5 AND 82.49999999,"B-",
IIf([Grade] BETWEEN 69.5 AND 79.49999999,"C",
IIf([Grade] <= 69.49999999,"F", NULL))))))) As Letter2,
But even then only the high points with >
are needed since you nest all conditions together.
IIf([Grade]>92.5,"A",
IIf([Grade] > 89.5,"A-",
IIf([Grade] > 86.5,"B+",
IIf([Grade] > 82.5,"B",
IIf([Grade] > 79.5,"B-",
IIf([Grade] > 69.5,"C",
IIf([Grade]<=69.5,"F", NULL))))))) As Letter3
However, as @MatBailie suggests, consider a lookup table and run a range join query (with comma separated tables without any JOIN
) then filter by values. Consider even incorporating above 100 (for extra credit) and below zero with room to actually hit 0.5 endpoints. This also provides better maintenance in case you adjust grade points.
GradeLetter table
ID Letter MinValue MaxValue
1 A 92.5 1000
2 A- 89.5 92.4999999
3 B+ 86.5 89.4999999
4 B 82.5 86.4999999
5 B- 79.5 82.4999999
6 C 69.5 79.4999999
7 F -1000 69.4999999
Range Join Query
SELECT l.Letter, g.Grade
FROM Grades g, GradeLetter l
WHERE g.Grade
BETWEEN l.MinValue AND l.MaxValue;
Upvotes: 1
Reputation: 133360
could be that using Switch
is a bit more simple eg
SELECT
Switch(
[Grade]>92.5,"A",
[Grade]>=89.5, "A-",
[Grade]>=86.5, "B+",
[Grade]>=82.5, "B",
[Grade]>=79.5, "B",
[Grade]>=69.5, "C",
[Grade]<69.5, "F") AS my_grade
FROM my_table
Upvotes: 4