counting number of occurrences per user in google sheets - google-sheets

I'm using a google form to populate a google sheet similar to the template here which we use for tracking discipline at a public school
https://drive.google.com/previewtemplate?id=0Agoue3Pq0fSGdDJzX0pfb25xLXlQdFp4SnBVRjVDdVE&mode=public
Teachers fill out a form when students break a rule and the results are recorded in a form
I'm trying to rearrange the data into a report where the outputs would be listed on a new sheet by how many times a given student had violated a rule rather than each instance of a rule violation.
The input table looks a lot like the one linked, but for simplicites sake you can imagine
A B C D
Last name|First name|student ID#|rule violated
The rules are filled in by a form and the teacher selects from pre-determined rule violations
For the output I'm trying to use a query to get the data to look like this
Last name|First name|student ID#|cell phone|skateboard|swearing|kissing|
Does anyone know of a way to do this with a google sheets command such a query?

You want to pivot on rule violation type: that is, make different types into separate columns. Here is a query that does this:
=query(A:E, "select A, B, C, count(E) where C is not null group by A, B, C pivot D", 1)
The query selects A,B,C, grouping by these contents, and separate the entries in D into columns, filling it with counts of violations. I included column E just to have something to run count() on. The content of that column is irrelevant; it could be empty. (Google Sheets require counting by a column that isn't otherwise selected or pivoted on, so I could not use A,B,C, or D.)

Related

Google Sheets: Dynamic lookup across two (merged) sheets

I have two external GSheets that are set up as room bookings with a running date in col B and the different rooms ppl can book in col C-AX for Sheet1, C-X for Sheet2, as well as my own Sheet with a list of names (let's call it NameSheet).
Example:
Goal: I want to add an extra column in NameSheet that returns all dates within the next two weeks in which a person has booked a room as well as the room info. Like this:
I used IMPORTRANGE to import both Sheets into my own Sheet (Merged_Sheet) and then merge them dynamically using a simple query formula:
=QUERY({'Sheet1'!A:AX;'Sheet2'!A:AX},"select * where Col1 <>''")
(I had to expand Sheet 2 to AX in order to merge them.)
I then set up another sheet (Date_Filter) to dynamically filter on the next two weeks:
=filter('Merged_Sheet'!A:AX,'Merged_Sheet'!B:B<=today()+7*1)
Finally, I have so far only managed to add a column in my original NameSheet that counts the number of times a there is a partial match on a name in the Merged_Sheet:
=countif(Date_Filter!A:AX,"*"&Name&"*")
Now I'm stuck on how I can return the dates & room info on a partial match (the name columns in the room sheet are "[First Name] [Last Name]" while the employee sheet is set up as "[Last Name],[First Name]") across an entire sheet. I've tried using regexmatch, filter, contains, and even the query function again, but I keep getting function errors.
I would super appreciate any formula help. :)

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.

Vlookup and creating IDs with an array formula

I have an event sign up form on Google forms on which students can select one of many events to sign up for. I'd like to compile the form data so that for each person who signs up for Event A, they are given a ID (i.e. first sign up gets 1, second gets 2, etc.) but I'd like this to be independent from Event B.
I thought of using VLookup to first find the event, and then I thought of having each ID generated with a be a simple cell + 1 formula, but I'm not sure how to do that with an array. In addition, I'm not sure how to do that with multiple events on the form. Because Event B would need to start from 1 as well.
I'm not sure this can be done with an arrayformula but you can use a formula like this that is copied all the way down the column. The output is blank if there is no timestamp value in column A:
=IF(LEN(A2:A),C2&COUNTIF(INDIRECT("C1:C"&ROW(C2)),C2),)
It assumes the Event ID is held in column C so amend as appropriate for your data
See it working in this example sheet:
https://docs.google.com/spreadsheets/d/1AiQcEyFKw5sXZ1W7Em5f_gjNx3OC9r1Kw7k4YtbkwAk/edit#gid=0
I used a query function to pull the data out to make separate sheets for each event:
=query('Form Responses 1'!A1:E, "select A, B, C, D, E where E='The East Tennessee History Museum'",)
I then used Chris Hick's function to number the participants
=ArrayFormula(IF(LEN(A2:A),ROW(A2:A)-1,))
That worked great!

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?

using both QUERY and FILTER together in a single statement?

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'))))

Resources