Google Sheet Query Function - Combine 2 Steps together in Query - google-sheets

Pl. refer the Sheet shared below -
https://docs.google.com/spreadsheets/d/1r0_oHLTcT9tmTJPgKVgkGwGWhooBM8uluwmWcC92eOk/edit?usp=sharing
Rank for diff. factors is calculated in Rank Sheet in Table A. Rank!ColL calculates combine score (D+ G + J).
PF Sheet Range - Z:AE have Step wise calculation and results expected.
1 - Objective is to get results of used Query(Rank!C8:L220,"Select C,L where D > F12 & L > 0.5 order by L desc",1) (ref. cell PF Sheet!AE17).
Query is referencing RANK Sheet's Cols.
2 - Possibility of merging Combine Score calculation as base data in Query.
Do revert is more clarity is reqd.

I reviewed the Sheet, and I can make some suggestions.
Since you are calling 2 columns with the Query, add 1 column to the right of AE, and that one will be the new AF.
After that, modify the formula from:
=query(Rank!C8:L220,"Select C,L where D > 0.25 & L > 0.5 order by L desc",1)
to:
=query(Rank!C8:L220,"Select C,L where D > 0.25 and L > 0.5 order by L desc",1)
The reason it was not working is the use of & instead of and as mentioned here.
To make reference to a specific Cell instead of a value. You can use "&F12&", Like this:
Reference
QUERY function

Related

Use QUERY to get Avg of last x entries matching conditions

I'm trying to refine my coding for a working spreadsheet by updating all the code to QUERY functions. One thing I am stuck on is where I average the last x rows matching specific conditions.
I was hoping that the following formula would work:
=QUERY(Ladder!A2:AE,"Select Avg(J) where F = '"&H$1&"' order by B desc limit "&$C$5)
My thought being that this would return the average of the last 3 rows - but I receive the
COL_IN_ORDER_MUST_BE_IN_SELECT error.
I only want the formula to return a single cell with the % average in it.
I realise that I could use the following code and then QUERY the Avg of that, but I want to be able to return % values for each different deck.
Here's a link to a cut down version of the spreadsheet:
Spreadsheet
Ladder: Where I enter the data
Ladder Filter: Where the data will filter based on query commands depending on criteria in the Ladder Stats tab
Ladder Stats: Where I can view all statistics and generate various statistical reports
It's all working at the moment, but as you can see it's very clunky and formula-heavy. I've worked most of it out except for the scenario you will find on the "Ladder Stats" tab - whereby B3="" and C5 != NULL. It is designed to give statistics for the last x games played by each of the decks.
you can either use a double query like this and format cell as %
=QUERY(QUERY(Ladder!A2:AE,
"select J
where F = '"&H$1&"'
order by B desc
limit "&$C$5, 0),
"select avg(Col1)
label avg(Col1)''", 0)
or you can use AVERAGE formula and click twice to get decimal position:
=AVERAGE(QUERY(Ladder!A2:AE,
"select J
where F = '"&H$1&"'
order by B desc
limit "&$C$5, 0))

Google Query Language for sum of result using cell reference in query

Hello and thanks for your help. I'm new to GQL but have good SQL experence and think I may be missing something small.
I have 2 sheets i'm working with
Main sheet
Colum G
InstanceID
i-554532f4693fc6186
i-09554fcda5f2f3262
i-0047551ae514412d5
-
Data Sheet
Colum A Colum B
i-554532f4693fc6186 10.12
i-554532f4693fc6186 12.12
i-554532f4693fc6186 13.12
i-554532f4693fc6186 17.12
i-554532f4693fc6186 30.12
I am trying to write a query that will find all the rows that match the Instance ID in column G against the datasheet Column A and return the AVG of all the matches in column B, the top 5 max, and top 5 min.
I'm finding that I can't point the query to a cell for referencing the instance ID. Is there a way?
I'm using this to try to get the max and it works for 1 but I ned the top 5 or any number.
=sort(query('HeC-Metrics'!A:B,"select max(B) Where A = 'i-044532f4693fc6186'"))
I'm OK needing to do different queries for each of the required results, AVG, min, max. I would also like to reference the cell in the G column so I don't have to manually enter the InstanceID.
Thanks your time.
Stephen
So it's just a case of getting the right syntax to use a cell value as a match in the query
=query(Sheet2!A:B,"select avg(B) where A='"&G2&"' group by A label avg(B) ''",1)
Note that you don't really need the group by if you already have a list of distinct ID's to compare against, but you can't have an aggregate like avg without it.
To get the bottom 5, you can use filter & sortn
=transpose(sortn(filter(Sheet2!B:B,Sheet2!A:A=G2),5))
(I have transposed the result to get it in a row (row 2) instead of a column)
or you could use a query
=transpose(query(Sheet2!A:B,"select B where A='"&G2&"' order by B limit 5 label B '' ",1))
Similarly to get the top 5 you could use
=transpose(sortn(filter(Sheet2!B:B,Sheet2!A:A=G2),5,,1,false))
or
=transpose(query(Sheet2!A:B,"select B where A='"&G2&"' order by B desc limit 5 label B '' ",1))
This begs the question of whether you could get these results (a) without needing a list of distinct values and (b) in a single array formula without copying down.
You could certainly get the distinct ID's and averages straight away from a query. Getting the top or bottom n values from a number of groups is much more difficult. I have attempted it in a previous question, but it requires a long and unwieldy formula.

How to get the sum of a column up to a certain value?

I have a google sheet that I am using to try and calculate leveling and experience points. Column A has the level and Column B has the exp needed to reach the next level. i.e. To get to Level 3 you need 600 exp.
A B
1 200
2 400
3 600
...
99 19800
In column I2 I have an integer for an amount of exp (e.g. 2000), in column J2 I want to figure out what level someone would be at if they started from 0.
Put this in column J and ddrag down as required. Rounddown(I2,-2) rounds I2 down to the nearest 100. Index match finds a match in column B and returns the value in column A of the matched row.
=index(A2:A100,match(ROUNDDOWN(I2,-2),B2:B100,0))
Using a helper column (for example Z): put =sum(B$1:B1) in cell Z1 and drag down. This will compute the sums required for each level. In J2, use the formula
=vlookup(I2, {B:B, Z:Z}, 2) + 1
which looks up I2 in column B, and returns the nearest match that is less than or equal to the search key. It adds 1 to find the level that would be reached, because your table has this kind of an offset to you: the entry against level N is about achieving level N+1.
You may want to put 0 0 on top of the table, to correctly handle the amounts under 200. Or treat them with a separate if condition.
Using algebra
In your specific scenario, the point amount required for level N can be computed as
200*(1+2+3+...+N-1) = 200*(N-1)*N/2 = 100*(N-1/2)^2 - 25
So, given x amount of points, we can find N directly with algebra:
N = floor(sqrt((x+25)/100)+1/2)
which means that the formula
=floor(sqrt((I2 + 25) / 100) + 1/2)
will have the desired effect in cell J2, without the need for an extra column and vlookup.
However, the second approach only works for this specific point values.

Compute subranks in spreadsheet column in combination with ArrayFormula (Google Sheets)

I'm trying to find the inverse rank within categories using an ArrayFormula. Let's suppose a sheet containing
A B C
---------- -----
1 0.14 2
1 0.26 3
1 0.12 1
2 0.62 2
2 0.43 1
2 0.99 3
Columns A:B are input data, with an unknown number of useful rows filled-in manually. A is the classifier categories, B is the actual measurements.
Column C is the inverse ranking of B values, grouped by A. This can be computed for a single cell, and copied to the rest, with e.g.:
=1+COUNTIFS($B$2:$B,"<" & $B2, $A$2:$A, "=" & $A2)
However, if I try to use ArrayFormula:
=ARRAYFORMULA(1+COUNTIFS($B$2:$B,"<" & $B2:$B, $A$2:$A, "=" & $A2:$A))
It only computes one row, instead of filling all the data range.
A solution using COUNT(FILTER(...)) instead of COUNTIFS fails likewise.
I want to avoid copy/pasting the formula since the rows may grow in the future and forgetting to copy again could cause obscure miscalculations. Hence I would be glad for help with a solution using ArrayFormula.
Thanks.
I don't see a solution with array formulas available in Sheets. Here is an array solution with a custom function, =inverserank(A:B). The function, given below, should be entered in Script Editor (Tools > Script Editor). See Custom Functions in Google Sheets.
function inverserank(arr) {
arr = arr.filter(function(r) {
return r[0] != "";
});
return arr.map(function(r1) {
return arr.reduce(function(rank, r2) {
return rank += (r2[0] == r1[0] && r2[1] < r1[1]);
}, 1);
});
}
Explanation: the double array of values in A:B is
filtered, to get rid of empty rows (where A entry is blank)
mapped, by the function that takes every row r1 and then
reduces the array, counting each row (r2) only if it has the same category and smaller value than r1. It returns the count plus 1, so the smallest element gets rank 1.
No tie-breaking is implemented: for example, if there are two smallest elements, they both get rank 1, and there is no rank 2; the next smallest element gets rank 3.
Well this does give an answer, but I had to go through a fairly complicated manoeuvre to find it:
=ArrayFormula(iferror(VLOOKUP(row(A2:A),{sort({row(A2:A),A2:B},2,1,3,1),row(A2:A)},4,false)-rank(A2:A,A2:A,true),""))
So
Sort cols A and B with their row numbers.
Use a lookup to find where those sorted row numbers now are: their position gives the rank of that row in the original data plus 1 (3,4,2,6,5,7).
Return the new row number.
Subtract the rank obtained just by ranking on column A (1,1,1,4,4,4) to get the rank within each group.
In the particular case where the classifiers (col A) are whole numbers and the measurements (col B) are fractions, you could just add the two columns and use rank:
=ArrayFormula(iferror(rank(A2:A+B2:B,if(A2:A<>"",A2:A+B2:B),true)-rank(A2:A,A2:A,true)+1,""))
My version of an array formula, it works when column A contains text:
=ARRAYFORMULA(RANK(ARRAY_CONSTRAIN(VLOOKUP(A1:A,{UNIQUE(FILTER(A1:A,A1:A<>"")),ROW(INDIRECT("a1:a"&COUNTUNIQUE(A1:A)))},2,)*1000+B1:B,COUNTA(A1:A),1),ARRAY_CONSTRAIN(VLOOKUP(A1:A,{UNIQUE(FILTER(A1:A,A1:A<>"")),ROW(INDIRECT("a1:a"&COUNTUNIQUE(A1:A)))},2,)*1000+B1:B,COUNTA(A1:A),1),1) - COUNTIF(A1:A,"<"&OFFSET(A1,,,COUNTA(A1:A))))

Find and replace by multiple patterns

Suppose I've got a text values column (named Data), generated by =unique() function. Also, there is an array of patterns to find and replace for (Find and Replace columns).
Which formula should I use to scan each cell in Data for multiple patterns in Find and replace it, if match?
Data Find Replace Result
1 a c z a
2 b f y b
3 c e x z
4 d d
5 e x
6 c z
Tried =SUBSTITUTE() and =IF() functions, but it fails, when I set an array of patterns, instead of single one.
If the table you is in range A1:E7, try this formula
=TRANSPOSE(SPLIT(REGEXREPLACE(REGEXREPLACE(REGEXREPLACE(ARRAYFORMULA(CONCATENATE($B$2:$B$7&"|")),$C$2,$D$2),$C$3,$D$3),$C$4,$D$4),"|"))
You can read further about this in an older post and google docs forum.
Array solution
This formula takes range to replace, so it can be used for variable number of patterns:
=QUERY(ARRAYFORMULA({REGEXMATCH(A2,$B$2:$B$4),
REGEXREPLACE(A2,$B$2:$B$4,$C$2:$C$4)}),
"select Col2 order by Col1 desc limit 1")
or this one:
=INDEX(ArrayFormula(REGEXREPLACE(A2,$B$2:$B$4,$C$2:$C$4)),IFERROR(MATCH(A2,$B$2:$B$4,0),1))
or this:
=IFERROR(INDEX($C$2:$C$4,MATCH(A2,$B$2:$B$4,0)),A2)
The formula is need to be dragged down.
Single Formula & Array solution
Also this single ArrayFormula will do the trick:
=ArrayFormula(trim(transpose(query({IF(--REGEXMATCH(TRANSPOSE(A2:A7),$B$2:$B$4)=1,
REGEXREPLACE(TRANSPOSE(A2:A7),$B$2:$B$4,$C$2:$C$4),"");
TRANSPOSE(if(--not(REGEXMATCH(A2:A7,JOIN("|",B2:B4))),A2:A7,""))},,COUNTA(A2:A)))))
or this shorter formula:
=ArrayFormula(IFERROR(VLOOKUP(MATCH(A2:A7,B2:B4,0),{ROW(INDIRECT("a1:a"&COUNTA(C2:C4))),C2:C4},2,0),A2:A7))
Please, see explanations in Sample file

Resources