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))
Related
I would like to get an average percentage out of my sample, however, I need to use several conditions. I tried to use the AVERAGE and AVERAGEIF together with FILTER but everything returns an error and I think I'm incorrectly "merging" formulas.
You can find my test sheet here.
The rules I need to apply:
The score for individual rows is possible to find in the "Data" sheet in cell N and the total results should be visible in the sheet "Calculation" cell E.
As the sample is huge in real life, I need to filter out several pieces of information and add conditions:
to filter out all items where the code/ID starts with 0: Data!A:A&"", "^0.+"
to filter out all items that are matching the date in the Calculation sheet: Data!C:C=$B3
to filter all items with the specific name: Data!B:B=$A3
Any idea how to get the average % out of items with specific filters?
UPDATE
Expected results: I want to see the total average for a specific date, name, and ID, and let's say I would use these filters, then I would see only the final average percentage.
Test =100%
Test = 0%
Test = 100%
Total Average %: 66.7%
Also, I think the best way would be to use AVERAGEIFS, but I'm getting the error "Array arguments to AVERAGEIFS are of different size".
=AVERAGEIFS(Data!N:N,Data!B:B=$A3,Data!C:C=$B3,Data!A:A&"", "^0.+")
=IFERROR(AVERAGEIFS(Data!N3:N,Data!B3:B,A3,Data!C3:C,B3,ARRAYFORMULA(if(LEN(Data!A3:A),REGEXMATCH(Data!A3:A,"^0.+"),"")),TRUE),"")
or
=IFERROR(AVERAGE(FILTER(Data!N3:N,Data!B3:B=A3,Data!C3:C=B3,REGEXMATCH(Data!A3:A,"^0.+"))),"")
or
=IFERROR(INDEX(QUERY({Data!A3:C,Data!N3:N},"select avg(Col4) where Col1 starts with '0' and Col2 = '"&A3&"' and Col3 = '"&B3&"'"),2,0),"")
Trying to set up a formula where I can pull N counts based off multiple criteria including a date range. A typical Countif formula could work in theory:
=countifs(D2:D, J2, F2:F, J3, E2:E, J4, G2:G, J5, C2:C, ">="&TODAY()-7, C2:C, "<="&TODAY())
However, the problem I am facing is I want to be able to still pull the N count even if I leave one or more data validated cells the formula is pulling off of blank. In order to pull anything, you have to select one of the 4 data validated options. As you select more, the data gets more granular. Currently if I leave one cell blank, I then get a zero on the return. Need that not to happen
Any thoughts on how I could make this work?
I have done this with queries before, but I am not sure how to pull N count if use query. Happy to go that route as well if its easiest
use:
=COUNTA(IFNA(QUERY(C:G,
"select C
where 1=1 "&
IF(J2="",," and D = '"&J2&"'")&
IF(J3="",," and F = '"&J3&"'")&
IF(J4="",," and E = '"&J4&"'")&
IF(J5="",," and G = '"&J5&"'")&
" and C <= date '"&TEXT(TODAY(), "yyyy-mm-dd")&"'
and C >= date '"&TEXT(TODAY()-7, "yyyy-mm-dd")&"'", 0)))
Spreadsheet
Tab Ladder - Col J has a COUNTIFS formula that calculates % of matching criteria within the last 24hrs. I would like to limit the calculation to the last 10 matching entries within the 24hr window.
I have a stub formula in J35 outlining how I would like it structured. I have done a lot of searching, and while I have found a few examples of "Last x rows" - I haven't been able to translate those concepts to my specific needs.
Thank you in advance for your help!
instead of your:
=COUNTIFS($A$18:$A, ">"&Dates!$C$4+TIME(Dates!$C$3,0,0)-1,
$D$18:$D, $D35,
$H$18:$H, $H35,
$Y$18:$Y, "")
use:
=COUNTA(IFERROR(QUERY(FILTER(ROW($A$18:$A),
$A$18:$A>Dates!$C$4+TIME(Dates!$C$3,0,0)-1,
$D$18:$D=$D35,
$H$18:$H=$H35,
$Y$18:$Y=""), "limit 10")))
I have also discovered that the following nested QUERY would work - though I would have to restructure the sheet a little bit so that the formula was outside of the bounds of the QUERY so not to trigger a circular dependency.
=QUERY(QUERY($A$18:$Y, "Select T Where H = '"&$H35&"' and D = '"&$D35&"' and E = '"&$E35&"' Order by C desc limit 10", 0), "select avg(Col1) label avg(Col1)''", 0)
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.
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))))