Google Sheets Avg Query on empty columns (AVG_SUM_ONLY_NUMERIC) - google-sheets

Google Sheets average (avg) Query will fail with error AVG_SUM_ONLY_NUMERIC if any column in the dataset is empty. How you can overcome this?
Essentially, this occurs as the query is being run on a dynamically generated data set, therefore it's impossible to know what columns are empty beforehand. Moreover the query output "layout" must not change, so, if a column is empty, the query should return blank or 0 as for the faulty empty column.
Let's give it a look
Scenario: a Google Sheet is being used to insert markings for students tests.
When a single test is done by students, teacher assigns multiple grades for it. For instance, one marking for writing, one for comprehension, etc.
The sheet should finally build columns containing an average for all the markings assigned within the same date.
For instance, in the above sheet (link here), columns with markings given on December 16th (cols B,G,M,R,V) should be averaged in column AE.
Thanks to brilliant user Marikamitsos, this is achieved with the following query in cell AE4:
=ARRAYFORMULA(QUERY(TRANSPOSE(QUERY(TRANSPOSE(FILTER(B4:Z,B3:Z3=AE3)),
"select "&TEXTJOIN(",", 1, IF(LEN(A4:A),
"avg(Col"&ROW(A4:A)-ROW(A4)+1&")", )))&""),
"select Col2")*1)
How does the above works?
Dataset is filtered by date
Filtered dataset is transposed and an avg Query is run on it
Result dataset is being queried again to easily filter out labels
All this works fine until a student has no markings for a given date, as occurs in cell AG4: student Bob has no markings for October's 28th test, and the query will throw an error AVG_SUM_ONLY_NUMERIC.
Could there be a way to insert a 0 in the filtered dataset FILTER(B4:Z,B3:Z3=AE3) so that ONLY empty rows will be set to 0? This would prevent the query to fail, while avoiding altering the dataset layout.
Or could there be a way to ignore zeroes in avg query?
NOTE: students cannot be graded with '0' when skipping a test!

See if this works
=ARRAYFORMULA(QUERY(TRANSPOSE(QUERY(TRANSPOSE(FILTER(B4:Z+0,B3:Z3=AG3)), "select "&TEXTJOIN(",", 1, IF(LEN(A4:A), "avg(Col"&ROW(A4:A)-ROW(A4)+1&")", )))&""),"select Col2")*1)

Related

Combine / merge contents of columns in Google Sheet into a single column based on a condition

I have a spreadsheet with multiple columns. Each column represents a recipe. Each column has a week number (e.g. 2, 3, 4)... Below the week number, we have a variable number of ingredients. I want to be able to merge all the ingredients from a given week into a single column.
Sample Data
I know how to statically merge ranges e.g. {B4:B20;C4:C20} and I can also think of using an if statement to check the week value e.g. =if(B1=2,{B4:B20;C4:C20}) but that's not close to what I want. I need to check the range B1:Z1 for the value of the week and if that value is X (let's say 2) then take the ingredients in B2:B and tack them on to C2:C and so on...
If I'm understanding you correctly, this should do it:
=QUERY(FLATTEN(FILTER(B3:Z,B1:Z1=2)),"WHERE Col1 Is Not Null")
FILTER keeps (i.e., "filters in") only the data in B3:Z where the header is 2.
FLATTEN forms one column (blank cells and all) from the FILTER results.
QUERY keeps only non-blank (i.e., Is Not Null) entries from that single-column list.

Google Sheets Formula for Conditionally Counting Alpha Characters

I am looking for a formula that can perform the "COUNT" equivalent of "SUMIF". I have in 'Sheet A' running records of attendance, with column A as "Last Name," column B is "First Name," and column C is "Attendance." The attendance column has values of "P, A, L" for present, absent, or late (respectively). The sheet is automatically updated each day, as new data for the day's attendance are appended at the bottom of the sheet.
In 'Sheet B' I have each student's name, matching the syntax in the above sheet ("Last Name" "First Name"). In this sheet, I want to be able to count the number of instances of each, "P", "A", and "L".
So...I want to be able to count in Sheet A the number of times a student has a "A" in the attendance column, conditionally by student name. I know that with SUMIF you can sum a range conditionally. COUNTIF does not work to appropriately filter the values by the student name. I was not able to get DCOUNTA to work either.
Open to any suggestions, no matter how complex.
For anyone curious, I came up with my own crude solution.
I created a new sheet for each: Present, Absent Late. Within each sheet I ran a query: =QUERY({'Imported Data'!A:C}, "select * where Col3 = 'P'"). This query returned every record where an individual was marked "P". Repeat for "A" and "L" on their respective sheets.
In my main sheet, which records count totals, I used the COUNTIF: =COUNTIF(Present!D:D,C2). I had a small problem to work around in this, as I had my data imported with a "Last Name" and "First Name" column, but could not COUNTIF across two columns. So, I created an ARRAYFORMULA in each Present/Absent/Late sheet. This concatenated the name values, so I could search against that singular value in my main sheet. This was present in D:1 of Present/Absent/Late: =Arrayformula(A:A&", "&B:B).
A little duplication and I was able to create my own, automatically updated, attendance tracker.
You seem to have gone to a great deal of effort to work around a problem that does not exist. In general, where SUMIF works for adding then a very similar COUNTIF should work for counting. Because in most groups of modest size neither first names nor surnames are likely to be unique (even if the combinations are likely to be) it is generally a good idea to assign IDs to people. Concatenating Last Name with First Name is effective but other options can be more compact.
Assuming in Sheet B you have P, A and L respectively in C1:E1 (a unique set of Last Name in ColumnA and First Name in ColumnB) then in C2 the following may be adequate if copied across to E2 and C2:E2 down to suit:
=COUNTIFS('Sheet A'!$A:$A,$A2,'Sheet A'!$B:$B,$B2,'Sheet A'!$C:$C,C$1)
Sheets Imported Data and Present seem irrelevant.

How do I get QUERY function to return correct data?

So I have this spreadsheet with data in it, there are 29 columns and 54 rows.
On the 2nd sheet I'm trying to find all of the rows that fit a certain criteria.
For some reason, if I include the column X in my query data, the results are completely messed up. The 1st row of the result is just concatenating the first 23 rows together whether they fit the criteria or not. If I only include up to Column W the query is OK and it returns the correct results. But the problem is that I need to get data from Columns A and AB, so I need to include column X in my data range.
In this spreadsheet you can see the data on Sheet1, the query that includes column X on Sheet2, and on Sheet3 I have the same exact query except it only goes up to Column W and you can see the correct results there.
Basically, I need the query to return the value of Column A and Column AB for every row where Column B is marked with an "x".
Here is the sheet
Include the third parameter of query, which is the number of header rows:
=query(Sheet1!A2:X, "select A where B='x'", 1)
The parameter is optional, but if it's omitted, query will guess the number of header rows based on the data. Sometimes it guesses correctly, sometimes not (hence the dependence on what columns are included in the query). In your case, it decided that the table had 23 header rows and concatenated them in the output.
I don't know why you have arrayformula wrapper for query, it does not really do anything.
This is a duplicate of https://webapps.stackexchange.com/questions/103761/how-do-i-get-query-to-return-the-right-data which I answered hours ago:
You can use the Filter function to do this , with a literal array :

Google Sheets: selecting cell values based on another cell MAX values

I'm trying to make a database of students using Google Sheets. It contains info about students, groups and orders; orders can change students membership in groups (taken in a group, moved up to a new group, graduated, on leave, sent down). Here are sample database sheets and here is a detailed description of my DB structure (the sheet report_Groups is slightly changed, its previous variant, described on the link, is now named old_report_Groups).
I need a query that would select a list of present members of given group on the given date. That means that for each student I have to select
the name, the latter status before given date and corresponding group. And from this result select student names, where statuses are "Taken in" or "Moved Up" and group is the same as given one.
The problem is to select the latter status. It should be MAX(status), whose "since" date ≤ given date, but there's a well-known problem of selecting more than one field together with aggregate function. Here is a question which is very close to, but query from its "best" answer gives me error "QUERY:NO_COLUMN". I've even copied the sheet Raw from there and tried to perform proposed query (with the onliest modification — replacing commas with semicolons according to my locale restrictions) on the data it was reported to work on — same error (check Raw and report_Raw sheets in my DB). Other variant (via MMULT and TRANSPOSE) works, but it's perfomance is very poor.
What can you suggest me? Thanks in advance.
Update: I've found the solution with an issue (described in my answer).
To solve the issue I need to know an answer for a different question.
Here's the solution (with an issue described below).
A. Orders_Students is filtered for selecting rows, having "since" cell value ≤ given date (report_Groups!A2):
=QUERY(Orders_Students!B:E;"select E, B, C, D where E <= date '" & TEXT(report_Groups!A2;"yyyy-MM-dd") & "'";1)
This interim result is stored at the inner_report_Groups tab (it will be referenced few times in the next query).
B. inner_report_Groups is filtered for selecting MAX("since") values and corresponding row cell values for each student:
ARRAYFORMULA(VLOOKUP(QUERY({ROW(inner_report_Groups!A$2:A)\SORT(inner_report_Groups!A$2:D)};"select max(Col1) group by Col3 label max(Col1)''";0);{ROW(inner_report_Groups!A$2:A)\SORT(inner_report_Groups!A$2:D)};{3\4\5};0)
The formula above is used as inner query in report_Groups!D2 (also in D3, D4—with appropriate indeces).
C. The second query result is filtered to get students whose status is either "Taken in" or "Moved Up" and corresponding group is equal to the given group (report_Groups!B2 (also in B3, B4—with appropriate indeces)):
=TRANSPOSE(IFERROR(QUERY(<here is the formula from step B>);"select Col1 where Col3 = '" & B2 & "' and (Col2='Taken in' or Col2='Moved Up')";0)))
The formula above is used as outer query in report_Groups!D2 (also in D3, D4—with appropriate indeces). IFERROR is intended to display nothing if query result is #N/A.
That query displays the needed results as you can see in report_Groups tab. But as the query on step B searches the whole columns of inner_report_Groups, there's only a single given date can be analysed (or the query interim results for other given dates should be placed in different columns of inner_report_Groups or at the different tab. Is there any way to give an alias for an interim result to refer it in a single cell formula instead of keeping it on different tab?

Google query function

I am trying to return multiple records from a logbook into a final monthly statement... I'm using the query function but I do not get multiple records, it only displays the first match.
My sheets are from 1-31 for days of the month, then the last sheet labeled 717 is for Unit #717's monthly statement.
On Sheet 717, I would like to display information from sheets 1 through 31. Where column A=717, display values from columns B,C,D. Currently, it will only show me the first match. The amount column should show the corresponding rate for that row.
I hope my explanation is not confusing, any help is much appreciated. Thanks.
Here is a link to sample spreadsheet.
As you are concatenating the output of QUERY functions, you are actually performing an "array calculation", and you'll need use an "array calculation enabler", otherwise you will indeed only get the first applicable result.
=ArrayFormula(QUERY('1'!A3:G60;"select B where A=717")&QUERY('1'!A3:G60;"select C where A=717")&QUERY('1'!A3:G60;"select D where A=717"))

Resources