I'm trying to summarize some data. Each row has a Person's Name, Date, and Distance data. For any date, a Person might have multiple rows, which I'm trying to combine by summing the distance of all activiites on that date.
Data looks like this:
Name
Date
Distance
Person1
12/25/2022
50
Person1
12/26/2022
25
Person1
12/26/2022
10
Person2
12/25/2022
5
Person2
12/26/2022
10
Person2
12/27/2022
30
Summary table add up the total distances for each day:
Name
12/25/2022
12/26/2022
12/27/2022
Person1
50
35
0
Person2
5
10
30
I can't figure out how to build an array for Person/Date to sum for just that date.
Here's an example sheet where I've tried various vlookup, sumif and other methods but need can't isolate the name-date combo.
Here's an example sheet. Thanks!
https://docs.google.com/spreadsheets/d/1dQUlYD0gvLRm3n2JbEOxCw0JW7rDmKlvFsoyctjyans/edit?usp=sharing
You can try with this QUERY:
=query(B:D,"Select B,SUM(D) where B is not null group by B pivot C",1)
Related
I have 2 sheets, SheetA and SheetB. The Rows in each sheet are unsorted but there is a 1:1 map of Columns A on each sheet. I am trying to do something like sql, where i say:
=select B from SheetA where SheetA.name == SheetB.A2
SHEETA
name, age
foo, 20
gary, 30
--------
SHEETB
name, hobby, age
gary, kites, =select B from SheetA where SheetA.name == A2
foo, boats, ...
I was trying the query but that returns lists, which actually would be what i wanted, but the data is not expected to be sorted.
Like some LOOKUP? You can try with:
=XLOOKUP(A2,'Sheet B'!A2:A,'Sheet B'!B2:B ,,0)
And, if you want for the whole column'
=INDEX(XLOOKUP(A2:A,'Sheet B'!A2:A,'Sheet B'!B2:B ,,0))
I have a Google Sheet with two sheets in it.
The first sheet is a list of songs with Title, Library #, Composer, ..., Last Performance Date
The second sheet is a list of performance dates with Title, Library #, date 1, date 2, ..., date n
Sheet 1 Example:
Title, Library #, Composer, Last Performance Date
Hip Song 1007 David {formula}
Slow Song 1002 Bob {formula}
Other Song 1004 David {formula}
Sheet 2 Example:
Title, Library #, Dates ->
Slow Song 1002 2021-01-12 2021-02-15
Other Song 1004
Hip Song 1007 2021-01-05
How can I automatically fill in the "Last Performance Date" column on the first sheet by looking up the song on the second sheet by the "Library #" and getting the last value in that row (with a variable number of dates per song on the second sheet).
With the example above, the Last Performance Date for "Hip Song" would be "2021-01-05", "Slow Song" would be "2021-02-15", and "Other Song" would be "" (an empty string or nothing).
For any given song, there could be no dates on the second sheet or a 100+ dates on that song's row.
I'd add a helper column to Sheet2 that contains the formula that calculates the "latest" date for a given song:
Sheet2
A
B
C
D
E
1
Title
Library #
Latest Date
Dates
2
Slow Song
1002
=IF(MAX(D2:E2)=0,"",MAX(D2:E2))
2021-01-12
2021-02-15
3
Other Song
1004
=IF(MAX(D3:E3)=0,"",MAX(D3:E3))
4
Hip Song
1007
=IF(MAX(D4:E4)=0,"",MAX(D4:E4))
2021-01-05
The IF(X=0,"",X) part of the formula is so that songs that don't have any dates show up as blank instead of 0 (which will get formatted as 1899-12-30).
Then, in Sheet1, use the VLOOKUP function to find the matching "latest date":
Sheet1
A
B
C
D
1
Title
Library #
Composer
Last Performance Date
2
Hip Song
1007
David
=VLOOKUP(B2,Sheet2!$B$2:$C$4,2,FALSE)
3
Slow Song
1002
Bob
=VLOOKUP(B3,Sheet2!$B$2:$C$4,2,FALSE)
4
Other Song
1004
David
=VLOOKUP(B4,Sheet2!$B$2:$C$4,2,FALSE)
Note the FALSE as the last parameter to VLOOKUP, which makes sure it will still return correct results, even if the data in Sheet2 is not sorted by Library #.
See this example spreadsheet.
if your dates (if present) are increasing with each next column try:
=INDEX(IF(B2:B="",,IFERROR(1*SPLIT(FLATTEN(QUERY(TRANSPOSE(IFNA(VLOOKUP(B2:B, Sheet2!B1:1000,
TRANSPOSE(SORT(SEQUENCE(COLUMNS(Sheet2!C1:1))+1, 1, 0))), 0)),,9^9)), " "))),,1)
demo spreadsheet
fx transcript: count columns from column with 1st date and create a sequence of number with +1 offset for each number. then sort the sequence in descending order and transpose it into row - this will be the 3rd parameter of vlookup which will return date columns in reverse order eg.: ..., Col5, Col4, Col3, Col2. so in vlookup we look for B2:B values in range Sheet2:B1:1000 and return multiple columns on each match. next, we transpose all results of vlookup and with query parameter ,,9^9 we collapse all rows of each column into a single row. next, we flatten the results and split by empty space (which was inserted after each date via query). in this stage, column with the latest date became our 1st column. next, dates are numeric values so we multiply them by 1 to catch errors of those cells that have no date only empty spaces. at last, we use simple if statement to check if B2:B range is empty. if so we return no value, otherwise we return date. and to limit the output only to 1 single column we use index to return all rows but only the first column
The query function looks at a separate sheet with orders entered by a dealer. In some months the dealer may not have a order. The B:B column in current sheet is all the dealers in Ascending order. Then I have separate columns for by month view with 3 columns per month. Number of contracts, amount then average. My query calculates correctly, but if a dealer doesn't have a contract then it skips. So my list is out of order. I'm needing it to place a 0 if no value found. I have 2 versions of the query.
J = amount, H = Dealer name, A = Date, the B = is the dealer list in current sheet.
This query populates but out of order due to skipping NUll or NA.
=QUERY('2021ContractsData'!A:V,
"Select COUNT(J),SUM(J),AVG(J)
WHERE MONTH(A)+1=1
Group By H LABEL COUNT(J) 'Contracts',SUM(J) 'Amount',AVG(J) 'Average'")
This query populates nothing, it shows the Header names but no values in rows.
=QUERY('2021ContractsData'!A:V,
"Select COUNT(J),SUM(J),AVG(J)
WHERE MONTH(A)+1=1
AND H='"&B2:B&"'
Group By H LABEL COUNT(J) 'Contracts',SUM(J) 'Amount',AVG(J) 'Average'")
Google Sheet View
try in C2:
={"Contracts", "Amount", "Average";
INDEX(IFNA(VLOOKUP(B3:B, QUERY('2021ContractsData'!A:V,
"select H,count(J),sum(J),avg(J)
where month(A)+1=1
group by H"), {2,3,4}, 0), 0))}
I have a table in Sheets that has 2 columns: (1) Station (2) Number of people at Station:
Station Number of People at Station
A 1
B 2
C 1
D 4
I want to have a new column in excel populate with Station names repeating in it's own row based on number of people at station. The expected output would be below:
Station Allocation
A
B
B
C
D
D
D
D
Is there a way to dynamically have this final table change based on the number of people at station? So if someone was to use a google sheet and they change Station A to 2 people, then there will now be 2 rows with A instead of 1.
Try:
=arrayformula({"Values";query(flatten(if(B2:B<>"",split(rept(A2:A&"|",B2:B),"|"),)),"where Col1 is not null",1)})
Replace "|" with a character that is not used in your dataset.
I've got a Google Sheet which holds the results of a monthly competition. The format is
Name | Date | Score
--------------------------------
Alan Smith | 14/01/2016 | 500
Bob Dow | 14/01/2016 | 450
Bob Dow | 16/01/2016 | 470
Clare Allie| 16/01/2016 | 550
Declan Ham | 16/01/2016 | 350
Alan Smith | 10/02/2016 | 490
Bob Dow | 10/02/2016 | 425
Declan Ham | 12/02/2016 | 400
Declan Ham | 12/02/2016 | 390
Clare Allie| 12/02/2016 | 560
I want to do 2 things with this data
I want to create a new sheet which holds the latest 'best' results. For the data presented here that would be
Alan Smith | 10/02/2016 | 490
Bob Dow | 10/02/2016 | 425
Declan Ham | 12/02/2016 | 400
Clare Allie| 12/02/2016 | 560
i.e. The results from February with the 'best' score per person. Here Declan Ham's lower score of '390' was removed.
I want another sheet to hold the tournament ranking. People are ranked by their top 3 monthly scores. i.e. The best score for each person for each month is obtained and the top 3 scores are combined to give their place in the tournament.
So far I've attempted to use Google queries, vlookups, filters to get these new sheets. But, just focusing on 1), the best I've been able to achieve is
=FILTER(Results!$A:$B, MONTH(Results!$B:$B) = MONTH(MAX(Results!$B:$B)))
Which will get me the results from the latest month. But it does not remove duplicates entries by people.
Does anyone have a suggestion for how I can achieve these requirements? Feel like I'm treading water at the moment.
Rather than trying to remove duplicates, you need to identify the maximum score by each person; you can do that by grouping values by person, then aggregating using max(). Here's how that would look, for the month of February 2016:
=query(Results!A1:C,"select A,max(C) where todate(B) > date '2016-2-1' group by A")
Instead of using a fixed value for the start of the latest month, we can get the year and month using spreadsheet formulas, and concatenate our query with them:
=query(Results!A1:C,"select A,max(C) where todate(B) > date '"&year(max(Results!B2:B))&"-"&month(max(Results!B2:B))&"-1' group by A")
That addresses your first question.
Tournament ranking
Your second goal is too complex for a single spreadsheet formula, in my opinion. Here's a way to accomplish it with multiple formulas, though!
The X & Y axes are filled out by spreadsheet formulas. On the X axis (orange), we populate participants names using this in cell A3:
=unique(Results!A2:A)
The Y axis consists of dates (green). These are the start dates of each unique month that there are scores for, calculated using the following formula in cell D2. This results in strings, e.g. 2016-01-1, and that format is specifically required for the later formulas to work.
=TRANSPOSE(SORT(UNIQUE(ARRAYFORMULA(TEXT(Results!B2:B13,"YYYY-MM-1")))))
Here's the formula for cell D3, which will calculate the sum of the 3 highest scores recorded for the user whose name appears in A3, for the month appearing in D2. (Copy & Paste the formula across the full range of participants & months, and it will adjust.)
=sum(query(Results!$A$1:$C,"select C where A='"&$A2&"' and todate(B) >= date '"&B$1&"' and todate(B) < date '"&IF(ISBLANK(C$1),TEXT(TODAY()+1,"yyyy-mm-dd"),C$1)&"' order by C desc limit 3 label C ''"))
Key points about that formula:
The query range needs to used fixed values so it isn't transposed when copied to additional cells. However, it's still open-ended, to absorb additional rows of scores on the "Results" sheet.
Results!$A$1:$C
A WHERE clause is used to select rows from the Results sheet that are for the given participant (A='"&$A2&"') and fall within the month that heads the column (C$1).
...and todate(B) < date '"&IF(ISBLANK(C$1),TEXT(TODAY()+1,"yyyy-mm-dd"),C$1)&"'
The best 3 scores for the month are found by first sorting the above result descending, then limiting the result to 3 rows.
...order by C desc limit 3
Finally, the QUERY headers are suppressed by this little trick, so that we get a single number as the result:
...label C ''
Individual tournament totals appear in column C, with a range SUM across the row, e.g. for cell C3:
SUM(D3:3)
The corresponding ranking in column B is then:
RANK(C3,C$3:C)
Tidy
For simpler copy/paste, you can do some error checking in these formulas, so that they can be placed in the sheet before the corresponding data is - for example, at the start of your season. Using IF(ISBLANK(... or IFERROR(... can be very effective for this.
B3 & down:
=IFERROR(RANK(C3,C$3:C))
C3 & down:
=IF(ISBLANK(A3),"",sum(D3:3))
D3 & rest of field:
=IFERROR(sum(query(Results!$A$1:$C,"select C where A='"&$A3&"' and todate(B) >= date '"&D$2&"' and todate(B) < date '"&IF(ISBLANK(E$2),TEXT(TODAY()+1,"yyyy-mm-dd"),E$2)&"' order by C desc limit 3 label C ''")))
Alternatively for the first part of your question (the latest 'best' results) , in addition to the solution provided by Mogsdad, this should also work.. :-)
=ArrayFormula(iferror(vlookup(unique(A2:A), sort(A2:C, 2, 0, 3, 0), {1,3}, 0)))
EDIT: This formula sorts the table with dates (col B) descending and col C descending and then (ab)uses the fact that vlookup only returns the first match to return the first and last column.