Determine the range category of a specified number - ms-access

So I have a column with different numbers and wish to categorize them by range within 30 minute intervals. So 5 would be 0-30, 697 would be 690-720, and 169 would be 150-180. I was first thinking of doing a case statement, but it doesn't look like Access 2003 supports it. Is there perhaps some sort of algorithm that could determine the range? Preferably, this would be done within the query.
Thank you.

Take the integer portion of (number / 30) using the Int function and multiply it by 30 to get your lower bound, then add 30 to that number to get your upper bound.
Examples
Int(5 / 30) = 0 * 30 = 0
Int(697 / 30) = 23 * 30 = 690

Use / (integer division) and * (multiplication).
5/30*30 = 0
697/30*30 = 690
169/30*30 = 150
...

Let x be your column with the values you want to catalogue, the in pseudo-SQL you have:
select ((x/30)*30) as minrange,
(((x/30)+1)*30) as maxrange
from yourtable
(you should take the integer part of the division).
Hope this helps.

This is fairly straight forward. You can just use the following.
(number \ 30) * 30
This will give you the lower index of your range. It does have one problem, which is that 30, 720, 180 etc, will be returned as themselves. This means your ranges either need to be 0-29, 690-719, etc, or have your caller take this into account.
This assumes you are using VBA where the '\' operator returns only the quotient. See more on VB operators here

Related

how to show only multiple of 25 in a sql record?

I have a plenty of record in MedicineStock field. i would like to only show the multiple of 25 in MedicineStock.. multiple of 25 [ 50 - 75 - 100.. etc ]
here's query i try
SELECT MedicineID,MedicineName,MedicineStock
FROM c a, MsMedicineType b
WHERE a.MedicineTypeID = b.MedicineTypeID
AND MedicineStock = MedicineStock+25
ORDER BY MedicineName
but it's not working. i'm still student i try to read the modules the teacher give.. but don't find any good refreence for it. and already looking for some refreence in google and couldn't find it. i'm totally stuck. i hope i'll get to know how to do it. in here. thank you in advance
Use the MOD function which represents the modulus operation in math.
MOD() returns the remainder of a number divided by another number, in your case, all multiples of 25 have 0 as remainder.
SELECT MedicineID,MedicineName,MedicineStock
FROM c a, MsMedicineType b
WHERE a.MedicineTypeID = b.MedicineTypeID
AND MOD(a.MedicineTypeID,25) = 0
ORDER BY MedicineName

How can I make my select statement deterministically match only 1/n of my dataset?

I'm processing data from a MySQL table where each row has a UUID associated with it. EDIT: the "UUID" is in fact an MD5 hash (VARCHAR) of the job text.
My select query looks something like:
SELECT * FROM jobs ORDER BY priority DESC LIMIT 1
I am only running one worker node right now, but would like to scale it out to several nodes without altering my schema.
The issue is that the jobs take some time, and scaling out beyond one right now would introduce a race condition where several nodes are working on the same job before it completes and the row is updated.
Is there an elegant way to effectively "shard" the data on the client-side, by specifying some modifier config value per worker node? My first thought was to use the MOD function like this:
SELECT * FROM jobs WHERE UUID MOD 2 = 0 ORDER BY priority DESC LIMIT 1
and SELECT * FROM jobs WHERE UUID MOD 2 = 1 ORDER BY priority DESC LIMIT 1
In this case I would have two workers configured as "0" and "1". But this isn't giving me an even distribution (not sure why) and feels clunky. Is there a better way?
The problem is you're storing the ID as a hex string like acbd18db4cc2f85cedef654fccc4a4d8. MySQL will not convert the hex for you. Instead, if it starts with a letter you get 0. If it starts with a number, you get the starting numbers.
select '123abc' + 0 = 123
select 'abc123' + 0 = 0
6 out of 16 will start with a letter so they will all be 0 and 0 mod anything is 0. The remaining 10 of 16 will be some number so will be distributed properly, 5 of 16 will be 0, 5 of 16 will be 1. 6/16 + 5/16 = 69% will be 0 which is very close to your observed 72%.
To do this right we need to convert the 128 hex string into a 64 bit unsigned integer.
Slice off 64 bits with either left(uuid, 16) or right(uuid, 16).
Convert the hex (base 16) into decimal (base 10) using conv.
cast the result to an unsigned bigint. If we skip this step MySQL appears to use a float which loses accurracy.
select cast(conv(right(uuid, 16), 16, 10) as unsigned) mod 2
Beautiful.
That will only use 64 bits of the 128 bit checksum, but for this purpose that should be fine.
Note this technique works with an MD5 checksum because it is pseudorandom. It will not work with the default MySQL uuid() function which is a UUID version 1. UUIDv1 is a timestamp + a fixed ID and will always mod the same.
UUIDv4, which is a random number, will work.
Convert the hex string to decimal before modding:
where CONV(substring(uuid, 1, 8), 16, 10) mod 2 = 1
A reasonable hashing function should distribute evenly enough for this purpose.
Use substring to convert only a small part so the conv doesn't overflow decimal range and maybe behave badly. Any subset of bits should also be well distributed.

How to create query with simple formula?

Hey is there any way to create query with simple formula ?
I have a table data with two columns value_one and value_two both are decimal values. I want to select this rows where difference between value_one and value_two is grater then 5. How can i do this?
Can i do something like this ?
SELECT * FROM data WHERE (MAX(value_one, value_two) - MIN(value_one, value_two)) > 5
Example values
value_one, value_two
1,6
9,3
2,3
3,2
so analogical difs are: 5, 6, 1, 1 so the selected row would be only first and second.
Consider an example where smaller number is subtracted with a bigger number:
2 - 5 = -3
So, the result is a difference of two numbers with a negation sign.
Now, consider the reverse scenario, when bigger number is subtracted with the smaller number:
5 - 2 = 3
Pretty simple right.
Basically, the difference of two number remains same, if you just ignore the sign. This is in other words called absolute value of a number.
Now, the question arises how to find the absolute value in MySQL?
Answer to this is the built-in method of MySQL i.e. abs() function which returns an absolute value of a number.
ABS(X):
Returns the absolute value of X.
mysql> SELECT ABS(2);
-> 2
mysql> SELECT ABS(-32);
-> 32
Therefore, without worrying about finding min and max number, we can directly focus on the difference of two numbers and then, retrieving the absolute value of the result. Finally, check if it is greater than 5.
So, the final query becomes:
SELECT *
FROM data
WHERE abs(value_one - value_two) > 5;
You can also do complex operations once the absolute value is calculated like adding or dividing with the third value. Check the code below:
SELECT *
FROM
data
WHERE
(abs(value_one - value_two) / value_three) + value_four > 5;
You can also add multiple conditions using logical operators like AND, OR, NOT to do so. Click here for logical operators.
SELECT *
FROM
data
WHERE
((abs(value_one - value_two) / value_three) + value_four > 5)
AND (value_five != 0);
Here is the link with various functions available in MySQL:
https://dev.mysql.com/doc/refman/5.0/en/mathematical-functions.html
No, you would just use a simple where clause:
select *
from data
where abs(value_one - value_two) > 5;

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.