MS access if condition doesn't work - if-statement

I used to have one query that does a bunch of things, one of them is tell me about the salary increase for each employee. Is it due? is it overdue? is it too early for one?
The query kept asking me to enter parameters and after asking this question removing "enter parameter value" in query MS access I broke the one query into a bunch, each query builds on the other until the last one that has the if condition.
Everything worked exactly the way I want it to, except for the if condition (that used to work fine before!!!)
This is my if condition
Eligibility: IIf([MonthsSinceLastIncrease] < 24, IIf([MonthsSinceLastIncrease] >= 18
AND [LastOfRatings] <= 2, "OVERDUE", IIf([MonthsSinceLastIncrease] >= 15
AND [LastOfRatings] = 1, "OVERDUE", IIf([MonthsSinceLastIncrease] >= 9
AND [MonthsSinceLastIncrease] < 15
AND [LastOfRatings] = 1, "Eligible", IIf([MonthsSinceLastIncrease] >= 12
AND [MonthsSinceLastIncrease] < 18
AND [LastOfRatings] = 2, "Eligible", "ok")))), "OVERDUE")
The rule for salary increases are as follows:
If the employee's rating is 3, he gets an increase after 24 months of
his last one
If the employee's rating is 2, he gets one in 12-18
months
If the employee's rating is 1, he gets one in 9-15 months
What happens now, is that for some of the employees, I get only one record and it's correct, but for some employees, I get two records, one of them is correct an the other is not. Now instead of 48 records (what I used to get when the condition worked fine), I get 58.
This is the code for the whole query
SELECT IIf([MonthsSinceLastIncrease] < 24, IIf([MonthsSinceLastIncrease] >= 18
AND [LastOfRatings] <= 2, "OVERDUE", IIf([MonthsSinceLastIncrease] >= 15
AND [LastOfRatings] = 1, "OVERDUE", IIf([MonthsSinceLastIncrease] >= 9
AND [MonthsSinceLastIncrease] < 15
AND [LastOfRatings] = 1, "Eligible", IIf([MonthsSinceLastIncrease] >= 12
AND [MonthsSinceLastIncrease] < 18
AND [LastOfRatings] = 2, "Eligible", "ok")))), "OVERDUE") AS Eligibility
,MonthsSinceLastUpdateQ.LocalID
,MonthsSinceLastUpdateQ.LastOfRatings
,MonthsSinceLastUpdateQ.MaxOfDateOfUpdate
,MonthsSinceLastUpdateQ.MonthsSinceLastIncrease
FROM MonthsSinceLastUpdateQ
,DateOfUpdateQ
GROUP BY IIf([MonthsSinceLastIncrease] < 24, IIf([MonthsSinceLastIncrease] >= 18
AND [LastOfRatings] <= 2, "OVERDUE", IIf([MonthsSinceLastIncrease] >= 15
AND [LastOfRatings] = 1, "OVERDUE", IIf([MonthsSinceLastIncrease] >= 9
AND [MonthsSinceLastIncrease] < 15
AND [LastOfRatings] = 1, "Eligible", IIf([MonthsSinceLastIncrease] >= 12
AND [MonthsSinceLastIncrease] < 18
AND [LastOfRatings] = 2, "Eligible", "ok")))), "OVERDUE")
,MonthsSinceLastUpdateQ.LocalID
,MonthsSinceLastUpdateQ.LastOfRatings
,MonthsSinceLastUpdateQ.MaxOfDateOfUpdate
,MonthsSinceLastUpdateQ.MonthsSinceLastIncrease;
Your help is much appreciated, please note that I barely know coding and have only been learning MS Access as I go, thank you!

Tables in your query not linked. Link related colums in query designer by drag-and-drop, like relationship creation

Related

How to count the number of questions that have the average score below 3.0

Here is the table example. The decimal values are the averages. On the left are the course titles in one column. Across the matrix are the questions as string. The values are the averages which I'm trying to check which question has the value below 3.0 and count the number of questions which has the average value below 3.0 and show in one column.
In the screen shot below the question 2 for course 3 has average below 3.0 and also for course 2 the question 4 has value below 3.0 and I would like to count those questions and display in one column. Any ideas?
I also tried this but it only shows 1's in the last column instead of counting or summing all those question averages below 3.0. Any ideas on this? Test Measure = if([Question 1 Measure] < 3, 1, 0 + if([Question 2 Measure] < 3, 1, 0 + if( [Question 3 Measure] < 3, 1, 0 + if( [Question 4 Measure] < 3, 1, 0 + if([Question 5 Measure] < 3, 1, 0 + if([Question 6 Measure] < 3, 1, 0 + if([Question 7 Measure] < 3, 1, 0 + if( [Question 8 Measure] < 3, 1, 0 + if([Question 9 Measure] < 3, 1, 0 + if([Question 10 Measure] < 3, 1, 0 + if( [Question 11 Measure] < 3, 1, 0 + if( [Question 12 Measure] < 3, 1, 0 + if([Question 13 Measure] < 3, 1, 0 + if( [Question 14 Measure] < 3, 1, 0 + if([Question 15 Measure] < 3, 1, 0 + if( [Question 16 Measure] < 3, 1, 0 + if([Question 17 Measure] < 3, 1, 0 + if([Question 18 Measure] < 3, 1 , 0 + if( [Question 19 Measure] < 3, 1 ,0)))))))))))))))))))
Try this measure instead:
Number of Questions With Average < 3 =
SUMX(SUMMARIZE(
'Table','Table'[Question],"Average Score",[Overall Average]),
IF([Overall Average] < 3,1,0))
This measure creates a virtual table called Average Score, grouping the Overall Average by Question. Then it assigns a 1 to any group(question) that has an Overall Average less than 3 and a 0 otherwise. Then it sums it up.
Here are my results with some sample data:
If you don't like the '0's, try this:
Number of Questions With Average < 3 =
var result = SUMX(SUMMARIZE('Table','Table'[Question],"Average Score",
[Overall Average]), IF([Overall Average] < 3,1,0))
return IF(result, result)
This will only return a result if the result is not 0.
You can calculate the number of questions with an average score < 3 as follows:
Number of Questions With Scores < 3 = CALCULATE(COUNT('Table'[Question]), FILTER('Table', [Average Score] < 3))
However, you cannot add this as a separate column at the end of a matrix. If you have Average Score as the values in a matrix with Questions as the column headers and Courses as the rows, and you add this new measure to the values, you will get a column with this new measure for each question, and a total at the end:
To achieve the visual you are looking for, you would need individual average measures for each question; this would be very tedious if you have a lot of questions:
Question 1 Average Score = CALCULATE([Average Score], FILTER('Table', 'Table'[Question] = "Question 1"))
You will need to add this measure for each question by right clicking on the table you wish to add the measure to and selecting New measure:
Then, you could include each of the Question # Average Score measures and the Number of Questions with Scores < 3 as the values and get something like this:

How to set different (if) parameters for the same number in a list?

I don't even know how to format this paragraph right haha
Hi there I'm completely new to Python.
I was wondering if I have a list
how do I take the output of a first if command and use on the next
Example
L= [23, 91, 0, -11, 4, 23, 49]
for i in L:
if(i > 10):
print(i * 30)
example
I also want to check if the output of this number is an even number if so (+6) -- for the output of that
if number is not equal to -11 I want to add 10.
So I got 23 > 10= (23*30 = 690) // 690 is an even number ( 690 + 6=696) // it not equal to -11 so (696+10= 706).
How do I do this for every number on the list? Excuse my lack of knowledge it's literally my first python class and my first exercises.
Is that what you want?
L= [23, 91, 0, -11, 4, 23, 49]
for i in L:
if i > 10:
num = i * 30
if num % 2 == 0:
num += 6
if i != -11:
num += 10
else:
pass
print(num)
output:
706
2746
706
1486

Getting a set of random number between 2 numbers that have a certain mean. [duplicate]

This question already has answers here:
Get `n` random values between 2 numbers having average `x`
(5 answers)
Closed 6 years ago.
Problem: Getting a set of random numbers between two values that will have a certain mean value.
Let say we getting n number of random number where the number will be between 1 and 100. We have a mean of 25.
My first approach is to have 2 modes where we have aboveMean and belowMean where the first random number is the initial range 1 and 100. Every subsequent number will check the total sum. If the total sum is above the mean, we go to case aboveMean which is then get a random number between 1 and 25. If the total sum is below the mean, we do case belowMean then get a random number between 26 and 100.
I need some idea on how to approach this problem beside the crude get a random number to add it to the total then get the average. If it above the mean in question, we get a random number below the mean and so forth. While it does work, doesn't seem to be the best method.
I'm guessing I should brush up on probability to approach this random number generator.
Let us divide the range into left and right portions. Use a value from the portion at a frequency corresponding to the relative width of the other half.
int Leruce_rand(int min, int mean, int max) {
int r = rand()%(max - min + 1);
if (r < mean) {
// find number in right half
return rand()%(max - mean + 1) + mean;
} else {
// find number in left half
return rand()%(mean - min) + min;
}
Assumes mean is part of the right half. This quick solution likely has small bias.
Given OP's values, roughly, the average of the left half is 12.5 and called 75% of the time. Average of the right is 62.5 called 25% of the time: average 25.
This approach differs from OP's which "Every subsequent number will check the total sum. If the total sum is above the mean, we go to case aboveMean which is then get a random number between 1 and 25." As that absolutely prevents a set of occurrences above or below the mean. With RNG, the value generated should not be biased on the history of previous generated values.
There's literally an infinite number of ways to achieve this. For instance, generate 3 random numbers between 1 and 100 (std::uniform_int_distribution) and take the minimum of those (std::min(a,b,c)).
Obviously, for a mean of 75 you'll need to pick the maximum of 3 numbers.
The benefit of this method is that each outcome is independent of the previous ones. It's completely random.
Take some good distribution and use it. Say, Binomial distribution. Use B(99,24/99),
so sampled values are in the range 0...99, with parameter p equal to 24/99.
So if you have routine which sample from B, then all you need is to add 1
to be in he range 1...100
Mean value for binomial would be p*n, in this case equal to 24. Because you're adding 1, your mean value would be 25 as required. C++11 has binomial RNG in the
standard library
Some code (not tested)
#include <iostream>
#include <random>
int main() {
std::default_random_engine generator;
std::binomial_distribution<int> distribution(99, double(24)/double(99));
for (int i=0; i != 1000; ++i) {
int number = distribution(generator) + 1;
std::cout << number << std::endl;
}
return 0;
}
Assume a fair random(a,b) function (this question should not be about which random function is better) then simply just restrcting ithe ranges that is piced from should be a good start, like;
const int desiredCount = 16;
const int deiredMean = 25;
int sumValues = random(a,b);
int count = 1;
while (count < desriredCount - 1) {
int mean = sumValue/count;
int nextValue = 0;
if (mean < desiredMean) // Too small, reduce probablity of smaller numbers
nextValue = random(a+(desiredMean-mean)/(desriredCount-count),b);
else //too large, reduce probability of larger numbers
nextValue = random(a,b-(mean-desiredMean)/(desriredCount-count));
sumValue += nextValue;
count += 1;
}
int lastValue = desiredMean*desriredCount - sumValue/count;
sumValue += lastValue;
count += 1;
Note: The above is not tested, and my thinking is that the trimming of the upper and lower bound may not be sufficently aggressive to do the trick, but I hope that i will get you going.
Some boundary conditions, such as if you only want 2 numbers and a means of 25 from numbers between 0 and 100, the initial random number cannot be larger than 50, since that makes it impossible to pick the second (last) number -- so if you want the algo to give you exact mean values under all circumstances, then a bit more tweaking is needed.
OP's wants a set of numbers meeting certain criteria.
Consider generating all possible sets of n numbers in the range [min max] and then eliminating all sets but those with the desired mean. Now randomly select one of those sets. This would meet OP's goal and IMO would pass fair randomness tests. Yet this direct approach is potentially a huge task.
Alternatively, randomly generate lots of sets until one is found that meets the mean test.
The below meets OP's requirement of a specified mean without directly biasing the random numbers selected. Certainly not an efficient method when the desired mean is far from the min/max average.
#include <stdio.h>
#include <stdlib.h>
void L_set(int *set, size_t n, int min, int mean, int max) {
assert(n > 0);
assert(min >= 0);
assert(mean >= min);
assert(max >= mean);
size_t i;
long long diff;
long long sum_target = n;
unsigned long long loop = 0;
sum_target *= mean;
int range = max - min + 1;
do {
loop++;
long long sum = 0;
for (i = 1; i < n; i++) {
set[i] = rand() % range + min;
sum += set[i];
}
diff = sum_target - sum; // What does the final number need to be?
} while (diff < min || diff > max);
set[0] = (int) diff;
printf("n:%zu min:%d mean:%2d max:%3d loop:%6llu {", n, min, mean, max, loop);
for (i = 0; i < n; i++) {
printf("%3d,", set[i]);
}
printf("}\n");
fflush(stdout);
}
int main(void) {
int set[1000];
L_set(set, 10, 1, 2, 4);
L_set(set, 16, 1, 50, 100);
L_set(set, 16, 1, 25, 100);
L_set(set, 16, 1, 20, 100);
return 0;
}
Output
n:10 min:1 mean: 2 max: 4 loop: 1 { 4, 2, 4, 3, 2, 1, 1, 1, 1, 1,}
n:16 min:1 mean:50 max:100 loop: 2 { 45, 81, 24, 50, 93, 65, 70, 52, 28, 91, 25, 36, 21, 45, 11, 63,}
n:16 min:1 mean:25 max:100 loop: 3257 { 52, 1, 15, 70, 66, 30, 1, 4, 26, 1, 16, 4, 48, 42, 19, 5,}
n:16 min:1 mean:20 max:100 loop:192974 { 24, 10, 13, 3, 3, 53, 22, 12, 29, 1, 7, 6, 90, 11, 20, 16,}
you have to go into some probabilities theory. there are a lot of methods to judge on random sequence. for example if you lower the deviation you will get triangle-looking-on-a-graph sequence, which can in the end be proven not trully random. so there is not really much choice than getting random generator and discarding the sequences you don't like.
EDIT: this generates numbers in the range 1..100 with a theoretical mean of 25.25. It does this by using a random modulus in the range 1..100. Note that the required mean is 25, which is not exactly a quarter of the range 1..100.
OP wanted a way of varying the next number chosen according to whether the mean is less than or more than 25, but that lends some predictabilty - if the mean is more than 25 then you know the next "random" number will be less than 25.
The random calculation in the code is a very simple one line.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define RUNS 10000000
#define MAXN 100
int main() {
int n, i, sum = 0, min = MAXN, max = 0;
int freq[MAXN+1] = {0};
srand((unsigned)time(NULL));
for(i = 0; i < RUNS; i++) {
n = 1 + rand() % (1 + rand() % 100); // average modulus is (1 + MAX) / 2
if(max < n) {
max = n; // check that whole range is picked
}
if(min > n) {
min = n;
}
freq[n]++; // keep a tally
sum += n;
}
// show statistis
printf("Mean = %f, min = %d, max = %d\n", (double)sum / RUNS, min, max);
for(n = MAXN; n > 0; n--) {
printf("%3d ", n);
for(i = (freq[n] + 5000) / 10000; i > 0; i--) {
printf("|");
}
printf("\n");
}
return 0;
}
Program output showing distribution / 10000:
Mean = 25.728128, min = 1, max = 100
100
99
98
97
96 |
95 |
94 |
93 |
92 |
91 |
90 |
89 |
88 |
87 |
86 ||
85 ||
84 ||
83 ||
82 ||
81 ||
80 ||
79 ||
78 |||
77 |||
76 |||
75 |||
74 |||
73 |||
72 |||
71 ||||
70 ||||
69 ||||
68 ||||
67 ||||
66 ||||
65 ||||
64 |||||
63 |||||
62 |||||
61 |||||
60 |||||
59 |||||
58 ||||||
57 ||||||
56 ||||||
55 ||||||
54 ||||||
53 ||||||
52 |||||||
51 |||||||
50 |||||||
49 |||||||
48 |||||||
47 ||||||||
46 ||||||||
45 ||||||||
44 ||||||||
43 |||||||||
42 |||||||||
41 |||||||||
40 |||||||||
39 ||||||||||
38 ||||||||||
37 ||||||||||
36 ||||||||||
35 |||||||||||
34 |||||||||||
33 |||||||||||
32 ||||||||||||
31 ||||||||||||
30 ||||||||||||
29 |||||||||||||
28 |||||||||||||
27 |||||||||||||
26 ||||||||||||||
25 ||||||||||||||
24 ||||||||||||||
23 |||||||||||||||
22 |||||||||||||||
21 ||||||||||||||||
20 ||||||||||||||||
19 |||||||||||||||||
18 |||||||||||||||||
17 ||||||||||||||||||
16 |||||||||||||||||||
15 |||||||||||||||||||
14 ||||||||||||||||||||
13 |||||||||||||||||||||
12 ||||||||||||||||||||||
11 |||||||||||||||||||||||
10 ||||||||||||||||||||||||
9 |||||||||||||||||||||||||
8 ||||||||||||||||||||||||||
7 |||||||||||||||||||||||||||
6 |||||||||||||||||||||||||||||
5 |||||||||||||||||||||||||||||||
4 |||||||||||||||||||||||||||||||||
3 |||||||||||||||||||||||||||||||||||||
2 ||||||||||||||||||||||||||||||||||||||||||
1 ||||||||||||||||||||||||||||||||||||||||||||||||||||
OP did not state what kind of distribution was wanted, for example two straight lines pivoting at 25, or perhaps equal distribution each side of 25. However this solution is very simple to implement.

Explain this leap year Function C++

I'm having an issue with this code,I do not understand how the function works. I need to validate the input from the user, to see if their date that they placed is valid. And if it isn't I set the error code. So in my read function I cin the date then validate the input and call mdays() however, for some reason I don't know how to check in my if statement in the read function if the date is validate or not.
int Date::mdays() const
{
int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, -1};
int mon = _mon >= 1 && _mon <= 12 ? _mon : 13;
mon--;
return days[mon] + int((mon == 1)*((_year % 4 == 0) &&
(_year % 100 != 0)) || (_year % 400 == 0));
}
The code is very clever, written by someone who wanted to demonstrate that they are smart. I hate clever code. (It's also quite slow, I hate code that tries to be clever and fails).
Remember the rules for leapyears:
Every fourth year is a leap year. Except that every 100th year is not a leap year. Except that every 400th year is a leap year.
Most months you can look up from a table, except that February has either 28 or 29 days. So to understand the code, what happens if the month is not February? And what happens if the month is February? mon will be equal to 1. What is the value of (mon == 1) in February? How would you express the rules for leap years?
And the function that you showed calculates the number of days in a month, it doesn't do any validation. Obviously you need to know that April has 30 days to know that April 31st is invalid.
You can change the signature of mdays(), return a boolean to indicate if the date is validate or not, and put an output argument to store the days if the date is validate
bool Date::mdays(int& month_days) const {
int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (_mon < 1 || _mon > 12) return false;
mon--;
month_days = days[mon] + int((mon == 1)*((_year % 4 == 0) && (_year % 100 != 0)) || (_year % 400 == 0));
return true;
}
If you can modify the Date class, you should be able to create new method utilizing return value of mdays() like this:
bool Date::validate_day_and_month() const {
int maxday = mdays();
if ( maxday < 0 ) { return false; } // mdays() = -1 if _month is bad
if ( _day <= 0 || _day > maxday ) { return false; }
return true;
}
Here, _day is the day part of the user date input.

Precedence & Arity in strange statement

What is the execution order and possible results of this statement: leap = year%4 == 0;
(The left part is assignment and the right assertion?)
Which is excerpt from the following algorithm used to calculate day of the week of any date in Gregorian calendar:
static char daytab[2][13] =
{
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
for (year = 1; year <= y; year++)
{
leap = year%4 == 0;
if (year%100 == 0 && year%400 != 0)
leap = 0;
for (month = 1; month <= m; month++)
{
d += daytab[leap][month - 1];
daystotal = 365*(year - 1) + (int)floor((year-1)/4)
- (int)floor((year - 1)/100) + (int)floor((year - 1)/400) + d;
}
}
Look here operator precendence. year % 4 will be evaluated, than result will be compared to 0 and then result will be assigned to leap variable.
year % 4 == 0 is equivalent to (year % 4) == 0, which takes the remainder after dividing year by 4, then compares that to 0 and produces a Boolean result--true or false. You don't show a declaration/definition of leap, so we can only guess at its type. If it's a bool, that result will be assigned directly to it. Based on the later code:
if (year%100 == 0 && year%400 != 0)
leap = 0;
It appears that leap is probably some other arithmetic type (probably int). This is quite common, especially in code that was originally written in C90, which has no Boolean type.
In this case, the bool will be converted before the assignment. When being converted to arithmetic types, false converts to 0 and true converts to 1 (going in the other direction, 0 converts to false, and any other value converts to true).
So, the code has basically the same effect as something like:
if ((year % 4) == 0)
leap = 1;
else
leap = 0;
...or:
leap = ((year % 4) == 0) ? 1 : 0;
If I were writing it, I think I'd probably write the code more like this:
if ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0) )
leap = 1;
else
leap = 0;
...or (more likely) just:
leap = ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0));
At least to me, this more directly states the conditions of "what is a leap year" in the Gregorian calendar1. I suppose you could view the original code as a historical artifact through: it first computes whether it's a leap year under the rules of the older Julian calendar, then separately adds on the rules that were added in the Gregorian calendar. If somebody really wanted to reflect that history, however, they should probably include a comment explaining that that's why the code is written as it is. As it stands right now, rather than just computing the correct value, it starts by computing a value that may be incorrect, then checks for more conditions, and patches the value up afterward.
1. Which are, of course, something like: A year is a leap year if it is divisible by 4, and either not divisible by 100, or also divisible by 400. So, for example, 2000 was a leap year (divisible by 4 and also divisible by 400) but 1900 was not (divisible 4, but also divisible by 100 and not divisible by 400).