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?
Related
I have a Google Form that collects a bunch of data from dropdown questions on a Sheet with each question going to one column (as normal). On separate sheets, I want to be able to count how many times each option is selected.
Here is an example of what the response sheet might look like. A, B, and C are all questions.
I would then have separate sheets for 'Person?', 'Place?', and 'Thing?'. The 'Person?' sheet would look something like this:
I want to be able to add in the count of each time the option appears for that question. In the example, notice that 'Napoleon" is in both Col A and Col C. If I just count the number of times 'Napoleon' appears, I will get '2' even though he only appears once in the "Person?" responses.
I originally used a QUERY function like =QUERY('Input Data'!1:1000, "select count(A) where A contains '"&$A2&"'",0). BUT, I need it to be dynamic. So the "Person?" question may not always be Col A. I want the Query (or whatever formula) to search the headers and only return the count of that option for that question even if the column location changes.
Okay, I figured it out! In case someone else is curious, I used this formula:
=QUERY({'Input Data'!A1:L}, "SELECT COUNT(Col"&MATCH("Person?", 'Input Data'!1:1,0)&") WHERE Col"&MATCH("Person?", 'Input Data'!1:1,0)&" CONTAINS '"&$A2&"' label COUNT(Col"&MATCH("Person?", 'Input Data'!1:1,0)&") ''",0)
Lee, I sent you a PM about your most recent post, but in the process, I came across this one. There is no need for multiple formulas or manual entry references. One formula can produce the entire report with headers, listing and counts:
=IFERROR(QUERY(FILTER(FILTER(A:L,A:A<>""),A1:L1="Person?"),"Select Col1, COUNT(Col1) GROUP BY Col1 ORDER BY Col1 LABEL COUNT(Col1) 'Count'",1),"No Matches")
Just fill in the header your looking for between the quotes where Person? is now.
The double FILTERs mean "Start with only rows where Col A is not null and Row 1 reads 'Person?'"
Then QUERY simply returns the unique names in the left column and their counts in the right column. Because the QUERY had a final parameter of 1, any existing header will be kept (in this case, the one you were searching for); and the created column will receive a header (i.e., LABEL) of Count.
IFERROR will give a friendly error message if no matches are found (in which case check that what you entered for the search in the formula exactly matches a column header in the range).
here i have a sheet, in that we can find the sum of diff categories using query function by selecting from drop down list. but here I can select one month only at a time can i find the amount of January and February at the same time by adding another column for another month or in any other way. here I can find the sales of one month at a time. I want to find sales of two or three months at time.
Please help
https://docs.google.com/spreadsheets/d/1jdtrtdNQBsxiZt8FjvbaE9omCBs8x8vRgp0r2bc1_7c/edit#gid=0
There's no way you can make a drop down list with multiple choice in Google Sheets.
But there are some alternatives.
List of tick boxes (here as list of months)
Manual input of multiple values separated by comma or something else.
I give both:
Months are selected as list separated by | so it can be used as regex inside 'matches' clause in query
This generates list of months:
=join("|",query({A2:B7;C2:D7},"select Col2 where Col1 = true "))
Window with manual input works similar way
=substitute(substitute(F3,", ",","),",","|")
It takes its contents, removes spaces that are adjacent to comma, adds separator | instead of comma. It's case sensitive and I don't know how to get rid of this (?i) does not work within query.
All together it looks like on the picture and combined formula is:
=query(ORDERS!A1:R14,"select A, B, C , D where
A matches '"&join("|",query({A2:B7;C2:D7},"select Col2 where Col1 = true "))&"' and
B matches '"&substitute(substitute(F3,", ",","),",","|")&"'",0)
Here is my solution:
https://docs.google.com/spreadsheets/d/1fQ5_VdxZ-t4MqPbLqzb8q-saqp5Jqz3hVXeWHX_Lls4/copy
I copied your spreadsheet to do my testing. Here's what you can do.
Add another row of the same exact selection found on your "A" row.
Change your formula to this: ={query(ORDERS!A1:R,"Select * where A contains '"&$A2&"' and B contains '"&$B2&"'",1);query(ORDERS!A1:R,"Select * where A contains '"&$A3&"' and B contains '"&$B3&"'",0)}
What this does it run an array of two sets of formulas (In this case 2 queries) for the same set of data.
Here's the screenshot of the output if you're interested.
Sample Screenshot
I have a google sheet with all current staff information. I have a second sheet for when some piece of data needs changed. Last name, Location, job ect.
on second sheet I am looking to have someone:
Enter the user's first name in column B,
and or Last name in Column C,
I would like a drop down box generated in column D from the given info to contain all usernames found in the sheet with current information for all staff that have the given first and or last names provided.
Once a username has been selected, I can get all the pertinent data from that user with a vlookup from the sheet containing all staff info. For example if someone typed Scott in column B, I would like a drop down generated in column D with all staff that have a first name of Scott. Likewise if the last name was supplied and of course if both first and last was supplied.
Validation need to be done that's it,
1) Go to Staff Changes'!B2 and Data Validation> List from range & choose range from 'Staff Info'!B2:B
2) Select cell'Staff Changes'!D2 and Data Validation> List from range & range will be filter formula i.e 'Staffing Changes'N2:N.
Result
Few tweaks in vlookup:
I am not sure if you need username column twice if you don't need then change your vlookup formula from =vlookup(D2,'Staff Info'!A:K,10,0) to =VLOOKUP(D2,'Staff Info'!$G$1:$K,2,0)
Please provide access to trix in future so that changes & result can be shown in it.
UPDATE:
Use data validation as before & hide filter colum or use seperate sheet for filter formula & use query function in cell A3 =QUERY('Staff Info'!A:J,"select ' ',A,F,' ',' ',G,' ',I,' 'where A='"&A2&"' AND F = '"&B2&"' LABEL ' ''Date',' ''Current Last Name',' ''New Last Name',' ''New Building',' ''New Classification'",1) result wil be something like this
QUERY
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.
I hope someone can help me; I am building some spreadsheets to help with time-tracking. I have a list of tasks, with columns for criteria including date, hours spent, category of work, and client.
I want to filter this data by month, so for example I would like to know how long I spent in a single month on correspondence. This means I need to select all the rows where category = 'correspondence' and where the dates are all from one specified month. At the moment, I am having to use a query which outputs to an intermediary table, and then run a filter function on that table in order to output to my final table. Here are my two functions:
=QUERY( 'Task List'!A4:F , "select A, B, E, F where C = 'Correspondence'" )
that gives me the first table, with just the rows where the category is "Correspondence". Then, on that table, I have to run the next function:
=filter(J4:M,J4:J>=date(2015,4,1),J4:J<=date(2015,4,31))
To get only the rows from this month of April. If possible I would like to remove the intermediary table (which serves no other purpose and just clutters my sheet).
Is it possible to combine these statements and do the process in one step?
Thanks.
That is indeed possible.
Since you didn't specify in which column the dates are to be found (in the 'raw' data), I assumed for this example that dates are in col F. The easiest way would be to use the MONTH() function. However, when used in query(), this function considers January as month 0. That's why I added the +1. See if this works ?
=QUERY( 'Task List'!A4:F , "select A, B, E, F where C = 'Correspondence' and month(F)+1 =4 ")
I came to this question needing to filter by weeknum() and year() as well as query by contains(). It can be helpful to combine the query and filter functions for similar but more dynamic date and text matching needs. If for example the OP had needed to show this data by week, that is not available in the Google Query Language.
The filter function does not have the contains function so you are limited to exact match text or using Reg-Ex. The Query Lanuague does not have the Weeknum functions.
Combining Filter and Query can be useful in scenario similar to this question but with a dynamic timeline (no hard set month or date such as rolling timeline) and where the text your matching is not exact (when you need to use a contains function from query language).
Here is an example for combining filter and query in Google sheets.
=(sum(Filter(QUERY(FB!$A:$Z, "select Q where B contains 'Apple'"), Weeknum (QUERY(FB!$A:$Z, "select E where B contains 'Apple'")) = Weeknum($A8))))
In this example I queried Facebook ads data export for any posts which contained the word 'Apple' in their title, and where Weeknum() matched the ongoing weeks on my sheet, in order to pull weekly data from multiple sources into one table to build reports, with minimal updating required as the timeline runs on.
It selects Q(spend) Where B(title) contains Apple, and Weeknum(E) matches week number on current row of sheet(A8). I have found this useful many times. Query + Filter Example Sheet Here.
If OP wanted to pull this info dynamically as the months went on if A column contained months in order the formula could be pulled along and would automatically pull data from query data filtered by matching month month.
=(sum(Filter(QUERY( 'Task List'!A:Z , "select A, B, E, F, J where C contains 'Correspondence'" ), Month(QUERY( 'Task List'!A4:F , "select J where C contains 'Correspondence'" )) = Month('$A2'))))