Google Spreadsheet: Count for multiple criteria - function

K T
WW Data
34 1
34 3
34 4
35 2
35 5
36 1
36 0
How to count number of jobs where DATA>3 for WW=34?
I have tried on several methods but all doesn't work in Google spreadsheet.
method 1: =counta(iferror(filter(T:T;TRIM(T:T)>"3";TRIM(K:K)="34")))
method 2: =ArrayFormula(sum((K:K="34")*(T:T>"3")))
method 3: =ArrayFormula(sum(if(K:K="34",if(T:T>"3")))
method 4: =count(filter(T:T;T:T>"3";K:K="34"))
method 5: =iferror(index(query(K:T,"select count(T) where T>'3' AND K='34'"),2,1),"")
But all doesn't work...
Anyone can help??

I do not understand what you need to count, perhaps the following formulas can help you.
Columns number:
=QUERY(K:T; "SELECT COUNT(T) WHERE K = 34 AND T > 3 LABEL COUNT(T) ''")
You can also use a function like this:
=COUNTA(IFERROR(FILTER(T:T; VALUE(K:K) = 34; VALUE(T:T) > 3); ""))

Pay attention to data types!
Numbers/characters that are surrounded by single/double quotation marks, such as "3" and '3' are string literals, so T>"3" compares the value in T to the string "3", not the number 3.
Therefore, when you want to compare number values, you need to make sure that both your data and the value used for comparison are numbers at the time the actual comparison takes place.
The conversion may be done implicitly by the parser for some data types, (try =NOW()*2 :), or explicitly by you, either because you know the data type is not a number, or you take some sort of precaution with regards to the column's (unknown) data type, like using the VALUE() function, (as suggested by #wchiquito).
Remarks:
Some formats can "break" the VALUE() function as well, making it necessary to take further precautions... but this is beyond the scope of the current discussion.
When you import data from other applications, a column of normal or number values may be converted to string type by either the exporting or the importing application.

Related

Datetime to convert to ISO8601 format

I have a getdate() field and I want to convert it into 20210211T172650Z this format how do I do it in SSIS expression?
In SSIS, we have data types for strings, numbers and dates. Dates have no format and when it is converted to a string value, you're getting whatever format the localization rules dictate.
If you have a particular format you want, then you need to control that and the only way you can control it, is by using a string data type.
The pattern we're going to use here, for each element,
extract the digit(s)
convert the digits to string
left pad/prepend a leading zero
extract the last 2 characters from our string
When we extract digits, they're numbers and numbers don't have leading zeroes. We convert to string which will allow us to then add the character zero in front of it because we're just concatenating strings. If the number was less than 10, then this prepending of a zero will result in exactly what we want. 9 -> 09 If it was greater than 9, then we have an extraneous value in there. 11 -> 011. We don't care that we went too big because we're then going to take the right 2 most characters making 09 -> 09 and 011 -> 11. This is the shortest logic to making a leading zero string in SSIS.
Using that logic, we're going to create a variable for each element of our formatted string: year, month, day, hour, minute, second.
What's the starting date?
I created a variable called StartDate of type DateTime and hard coded it to a starting point. This is going to allow me to test various conditions. If I used getdate, then I'd either have to adjust my computer's clock to ensure my code works on 2001-01-01 at 01:01:01 as well as 2021-12-31 at 23:59:59. When you're satisfied your code passes all the tests, you can then specify that StartDate property EvaluateAsExpression is True and then use GetDate(). But I wouldn't use GetDate().
GetDate is going to evaluate every time you inspect it. When your package starts, it will show 2021-02-12 # 11:16 AM But your package takes 5 minutes to run, so when you go to re-use the value that is built on GetDate, you will now get 2021-02-12 # 11:21 AM.
In your case, those keys won't match if you send it more than once to your Amazon thing. Instead, use a System scoped variable like #[System::StartTime] That is updated to the time the package starts executing and remains constant for the duration of the SSIS package execution. So when you're satisfied the expression you've build matches the business rules, then change #[User::StartDate] over to use #[System::StartTime]. It provides the updated time but without the challenges of drifting time.
Extract the digit(s)
The SSIS expression language has YEAR, MONTH and DAY defined but no shorthand methods for time components. But, it does have the DATEPART function in which you can ask for any named date part. I'm going to use that for all of my access methods as it makes it nice and consistent.
As an example, this is how I get the Hour. String literal HOUR and we use our variable
DATEPART("HOUR",#[User::StartDate])
Convert the digits to string
The previous step gave us a number but we've got that leading zero problem to solve so convert that to a string
(DT_WSTR, 2)DATEPART("HOUR",#[User::StartDate])
Cast to string, two characters wide max, the number we generated
left pad/prepend a leading zero
String concatenation is the + operator and since we can't concatenate a string to a number, we make sure we have the correct operand types on both sides
"0" + (DT_WSTR, 2)DATEPART("HOUR",#[User::StartDate])
extract the last 2 characters from our string
Since we might have a 2 or 3 character string at this point, we're going to use the RIGHT function to only get the last N characters.
RIGHT("0" + (DT_WSTR, 2)DATEPART("HOUR",#[User::StartDate]), 2)
Final concatenation
Now that we have our happy little variables and we've checked our boundary conditions, the only thing left is to make one last variable, DateAsISO8601 type of string, EvaulateAsExpression = True
#[User::Year] + #[User::Month] +#[User::Day] + "T" +#[User::Hour] +#[User::Minute] +#[User::Second] + "Z"

SQL code reading nvarchar variable length

I am having trouble with a sequence of code that is not reading the NVARCHAR length of my variables (they are barcode strings). We have two different barcodes and the inventory system I have set up measures only the format of the original one (has 7 characters). The new barcode has 9 characters. I need to run a loop value through each barcode input, hence how I have set up this line of script.
I originally thought that a DATALENGTH or LEN function would suffice but it seems that it is only measuring the variable as an integer, not the 7 characters in the string. If anybody has any input of how to manipulate my code sequence or a function that will measure a variables nvarchar length, it would more than appreciated!
CASE WHEN #BarcodeID = LEN(7)
THEN UPPER(LEFT(#BarcodeID,2))+CONVERT(nvarchar,RIGHT(#BarcodeID,5)+#LoopValue-1)
ELSE UPPER(LEFT(#BarcodeID,3))+CONVERT(nvarchar,RIGHT(#BarcodeID,6)+#LoopValue-1) END
Once again, the LEN(7) function in the beginning seems to be my issue.
Perhaps what you're trying to do is actually
CASE WHEN LEN(#BarcodeID) = 7
By using #BarcodeID = LEN(7) you are basically testing to see if the #BarcodeID variable is equal to 1 because the LEN() function, "Returns the number of characters of the specified string expression." It is implicitly converting 7 to a one-character string.

How to generate 8 character unique string without checking if it exist in the database

I want to generate 1 million qr codes every day. every qr code should have random unique value. in order to achieve uniqueness i have two options as below
1)First option is to generate 8 characters alphanumeric random string and check if it is exist in database. if not exist then store in the database and if exist then retry gain.
The problem with this approach is that it takes around 45 minutes to generate 1 million unique alphanumeric strings because we have to check every time if generated alphanumeric string is present in the database or not.
2)Second option is to generate unique token by appending 6 characters alphanumeric string with time(hour+minute+second+date+month+year). with this option i am able to generate 1 million unique alphanumeric string within 5 minutes.
i am using this second option but the problem with this option is that the alphanumeric string generated from this is 15 characters long. i want to generate alphanumeric string with only 8 character long. if i use second option then timestamp itself takes 8 characters and string become easily guessable.
I want to know how to generate 8 characters random and unique alphanumeric string without checking if it exist in the database or not.
Using set structure is enough
def random_str(n):
base = 'abcefghijklmnopqrstuvwxzy0123456789'
return ''.join([base[ord(i) % len(base)] for i in os.urandom(n)])
s = set()
SIZE = 1000000
while len(s) < SIZE:
s.add(random_str(5))
And, it takes about 5 seconds.
Sorry, I missing every day. Split the 8 characters to tow part: the first part(3 characters) meaning every day or other conditions, can store it in Mysql and query before generate once or using days since 1970 and change it to 36 based number. The seconds part 5 characters using the code above to generate unique keys.
You could use symmetric encryption (example AES) to create your unique ids.
First, create a unique secret key.
Second, initialize a counter.
For every new code you want to generate, encrypt the current counter value with your encryption key and use it. And increment the counter.
PS: Only minor weird thing is you want to use alphanumeric output. So use a 32 bit key and you will get 32 bit output. Now, convert that into 8 byte alphanumeric output.
Try this ...
token = SecureRandom.urlsafe_base64(6) # This will give you 8 char uniq string
Hope this will work for you.
New plan.
Each day, take the numbers 000000..999999, shuffle them, base64 encode them (3 characters).
Take the number of days since your service started, as a six digit number, base64 encode that (3 chars). Good for a million days.
Note these numbers are unique and "random", but definitely not cryptographically secure at all.
EDIT some pseudo code:
int a[1000000];
int daysWeveBeenDoingThis;
for i from 0 to 999999 {
a[i] = i
}
ShuffleArray(a);
function getNthTokenToday ( int n ) {
String s = '';
long x =
(a[n] << 16L) + daysWeveBeenDoingThis);
for c from 0 to 5 {
v = (x >> (c*6)) & 63;
b = 'a-zA-Z0-9/.'[v];
s.append(b)(
}
return s;
}

Testing large input range scenarios with JUnit

I am pondering on how it is best to develop a JUnit test for a function that calculates a number of points and values in time based on a number of inputs. The purpose of the method is to calculate a series of points in time given a series of gradient value pairs, i.e.
Gradient 1 to Value 1, Gradient 2 to Value 2, Gradient 3 to Value 3, and so on...
Given a starting point in time and starting value, the function calculates the points in time each Value is reached (in the gradient value pairs) up until a target value is reached. This is essentially to plot a line on a graph with x-axis having date values and the y-axing having numeric values.
The method to test takes the following inputs:
StartTime (Date)
StartValue (Double)
TargetValue (Double)
GradientValuePairs (ArrayList)
EnsurePointEvery5Minutes (Boolean)
Where GradientValuePair is like:
class GradientValuePair {
Double gradient; // Gradient up to Target
Double target;
...
}
The output from this method is essentially ArrayList - a profile - with:
class DatePoint {
Date date;
Double value;
...
}
The EnsurePointEvery5Minuntes parameter basically adds a date point every 5 minutes for the calcualted profile which is then returned by the method.
To ensure the test has worked I will need to check each date and value is to what is expected by either:
Iterating through the array with an array of what is expected.
Store minute/second offsets from the StartTime with the expected value in some sort of structure.
Now the difficult part for me is deciding on how to write the TestCase. I want to test a broad/diverse range of inputs so that:
StartTime will cover 30 minutes i.e. in range of 2012-03-08 00:00 to 2012-03-08 00:30.
StartValue will be in the range of 0 to 1000.
TargetValue will be in the range of StartValue to 1000.
GradientValuePairs will require around 10 different arrays to be tested.
EnsurePointEvery5Minutes will be tested with both true and false.
Now given the number of different input sets will be something like:
30 * (0 to 1000 * 0 to 1000 = 500500) * 10 * 2 = 300,300,000 different test input sets per GradientValuePairs input
Or call us crazy for wanting to do this. Maybe the tests are too diverse for this instance.
I am wondering if anybody has any advice for testing such scenarios like this. I can't think of any other way to do this than implement my own algorithm for calculating the output before each call to the method I am testing - then who is to say that the algorithm I implement to test it is correct.
If I understand correctly. you are proposing that you test every possible set of combination of numeric inputs. That is almost never required of unit tests, as it would be essentially equivalent to testing whether the Java math library works for all numbers for all operations. Generally what you will do is try to identify edge conditions and write tests for those. These would include things like 0's. negatives, numeric overflow, and combinations of inputs which have intermediate computations that result in the same things. Then of course, you would want to test a handful of normal vanilla cases of data as well that are not edge cases.
So short answer: no you should not need to test 300M+ input sets.

Give an unique 6 or 9 digit number to each row

Is it possible to assign an unique 6 or 9 digit number to each new row only with MySQL.
Example :
id1 : 928524
id2 : 124952
id3 : 485920
...
...
P.S : I can do that with php's rand() function, but I want a better way.
MySQL can assign unique continuous keys by itself. If you don't want to use rand(), maybe this is what you meant?
I suggest you manually set the ID of the first row to 100000, then tell the database to auto increment. Next row should then be 100001, then 100002 and so on. Each unique.
Don't know why you would ever want to do this but you will have to use php's rand function, see if its already in the database, if it is start from the beginning again, if its not then use it for the id.
Essentially you want a cryptographic hash that's guaranteed not to have a collision for your range of inputs. Nobody seems to know the collision behavior of MD5, so here's an algorithm that's guaranteed not to have any: Choose two large numbers M and N that have no common divisors-- they can be two very large primes, or 2**64 and 3**50, or whatever. You will be generating numbers in the range 0..M-1. Use the following hashing function:
H(k) = k*N (mod M)
Basic number theory guarantees that the sequence has no collisions in the range 0..M-1. So as long as the IDs in your table are less than M, you can just hash them with this function and you'll have distinct hashes. If you use unsigned 64-bit integer arithmetic, you can let M = 2**64. N can then be any odd number (I'd choose something large enough to ensure that k*N > M), and you get the modulo operation for free as arithmetic overflow!
I wrote the following in comments but I'd better repeat it here: This is not a good way to implement access protection. But it does prevent people from slurping all your content, if M is sufficiently large.