I have simulated joining in google sheets with one =query function per row. If I put an aggregate function in there, this does not work anymore, since I'll always get two rows at least: 1 for displaying what aggegate function I have, one displaying the result:
=QUERY(Departments!B:N;"select N, max(C),max(M), max(J) where N="&A4&" group by N";0)
results in
max max max
21001 27.11.2022 20000 40000
even though I have the "headers" set to 0.
this is probably a bug in google sheets - but is there another way to get rid of the max's row?
use:
=QUERY(QUERY(Departments!B:N;
"select N,max(C),max(M),max(J)
where N="&A4&"
group by N"; ); "offset 1"; )
or:
=QUERY(Departments!B:N;
"select N,max(C),max(M),max(J)
where N="&A4&"
group by N
label max(C)'',max(M)'',max(J)''"; )
=QUERY(Departments!B:N; "select N, max(C) as MaxC, max(M) as MaxM, max(J) as MaxJ where N="&A4&" group by N"; 0)
or
=PIVOT(Departments!B:N; N; C, M, J; "MaxC", "MaxM", "MaxJ")
Related
I have tried many approaches but I can't seem to figure out a solution to a fairly simple problem with an array formula it seems:
I have a sheet where I get results of individual results of runs of a certain scientific experiment by row.
Next, I'd like to count the occurrence of each output value. Output values can be a number from 1 to 10 so I'd like to individually count how many times the output has been per value.
Also, I'd be then summing up how many individual outputs have been generated in total. So I'd be counting the number of unique outputs within a row.
Now my issue is that when using Arrayformula the way I normally use it it doesn't work because it would count and sum up everything for the whole Matrix specified. However, I just want the current row to be counted. I tried using ROW to get there, but i failed.
I also tried some things like =ARRAYFORMULA(SUMIF(IF(COLUMN(B1:F1),ROW(B2:F5)),ROW(B2:F5),B2:F5)) to understand how to apply the logic, but I fail to get it working as COUNTIF version if itself.
Test Sheet
Any help and ideas would be highly appreciated!
in H2 use:
=INDEX(MMULT(IF(INDIRECT("B2:F"&MAX((ROW(A2:A)*(A2:A<>""))))=""; 0; 1);
FLATTEN(COLUMN(B:F)^0)))
in J2 use:
=INDEX(ARRAY_CONSTRAIN(QUERY(QUERY({IFERROR(SPLIT(FLATTEN({ROW(A2:A)&"×"&B2:F}); "×"));
{SEQUENCE(10)*9^9\SEQUENCE(10)}};
"select count(Col1),Col1 where Col2 is not null group by Col1 pivot Col2");
"where Col11 < 100000 offset 1"; 0); 9^9; 10))
update:
H1:
={"Total No. of outcomes"; ARRAYFORMULA(IFNA(VLOOKUP(ROW(A2:A);
QUERY(SPLIT(UNIQUE(FLATTEN(ROW(B2:F)&"×"&B2:F)); "×");
"select Col1,count(Col1) where Col2 is not null group by Col1"); 2; 0)))}
J1:
=INDEX({"Occurence of "&SEQUENCE(1; 10); ARRAY_CONSTRAIN(QUERY(QUERY({IFERROR(
SPLIT(FLATTEN({ROW(A2:A)&"×"&B2:F}); "×")); {SEQUENCE(10)*9^9\SEQUENCE(10)}};
"select count(Col1),Col1 where Col2 is not null group by Col1 pivot Col2");
"where Col11 < 999999 offset 1"; 0); 9^9; 10)})
demo sheet
Just an afterthought to this, I think the accepted answer is optimal but I did wonder if you could solve it using only countifs. The answer is yes, but you have to force the array arguments to be the same size and shape otherwise you get the 'array arguments different sizes' error so in J2:
=ArrayFormula(countifs(B2:F6,mod(sequence(5,10,0),10)+1,row(B2:F6)+B2:F6-B2:F6,int(sequence(5,10,0)/10)+2))
Note the the total number of outcomes column gives the number of different outcomes using the formula below in H2:
=ArrayFormula(mmult(sign(J2:S6),sequence(10,1,1,0)))
For each of the email id, I want to get latest 10 records by timestamp. How do I get the results with arrayformula? Query function is not important as long as I can still achieve this with arrayformula. Here is the sample data:
https://docs.google.com/spreadsheets/d/1YAHA02VM-5MXzVKhkxu_eODPKObpoz441mGX8lOFu5M/edit?usp=sharing
Try this on another sheet, row 1:
=arrayformula(query({query({Sheet1!$A:$C},"order by Col1 desc,Col2",1),{"Dupe position";countifs(query({Sheet1!$A2:$C},"select Col2 order by Col1 desc,Col2",0),query({Sheet1!$A2:$C},"select Col2 order by Col1 desc,Col2",0),row(Sheet1!$A2:$C),"<="&row(Sheet1!$A2:$C))}},"select Col1,Col2,Col3 where Col1 is not null and Col4 <= 10 order by Col1",1))
You can adjust the number of records found by adjusting Col4 <= 10, and also the final sort by altering order by Col1 at the end of the formula.
Explanation
This gets the data from Sheet1, sorts it by date desc then email asc:
query({Sheet1!$A:$C},"order by Col1 desc,Col2",1)
Then to the side of this data, a COUNTIFS() is used to get the number each time an email appears in the list above (since it's sorted desc, 1 represents the most recent instance).
countifs(<EmailColumnData>,<EmailColumnData>,row(<EmailColumn>),"<="&row(<EmailColumn>))
In place of <EmailColumnData> in the COUNTIF() is:
query({Sheet1!$A2:$C},"select Col2 order by Col1 desc,Col2",0)
In place of <EmailColumn> above, we only want the row number so we don't need the actual data. We can use:
Sheet1!$A2:$C
Various {} work as arrays to bring the data together.
Eg., {a,b,c;d,e,f} would result in three columns, with a, b, c in row 1 and d, e, f in row 2. , is a new column, ; is a return for a new row.
A final query around everything gets the 3 columns we need, where the count number in col 4 is <=10, then sorts the output by Col1 (date asc).
On second thoughts, maybe this is bit cheeky, but this might do it ( taken from conditional rank idea )
=ArrayFormula(filter(A2:C,countifs(A2:A,">="&A2:A,B2:B,B2:B)<=10,A2:A<>""))
EDIT
The above assumes (because the data is time-stamped) dups shouldn't occur. If they do and the data is pre-sorted, you can use row number as a proxy for time stamp as suggested by #Aresvik.
Alternatively, you could count separately
(a) only rows with a later timestamp
plus
(b) rows with the same time stamp but with earlier (or identical) row number
=ArrayFormula(filter(A2:C,countifs(A2:A,">"&A2:A,B2:B,B2:B)+countifs(A2:A,"="&A2:A,B2:B,B2:B,row(A2:A),"<="&row(A2:A))<=10,A2:A<>""))
I have added a new sheet ("Erik Help") with the following formula in A1:
=ArrayFormula({"Submitted Time","Email","Score";SORT(SPLIT(FLATTEN(QUERY(SORT(TRANSPOSE(SPLIT(TRANSPOSE(QUERY(IF(Sheet1!B2:B=TRANSPOSE(UNIQUE(FILTER(Sheet1!B2:B,Sheet1!B2:B<>""))),Sheet1!A2:A&"|"&Sheet1!B2:B&"|"&Sheet1!C2:C,),,COUNTA(Sheet1!A2:A)))," ",0,1)),SEQUENCE(MAX(COUNTIF(Sheet1!B2:B,Sheet1!B2:B))),0),"LIMIT 10")),"|",1,0),1,0)})
The number of records is set after LIMIT.
The order is set by the final two numbers: 1,0 (meaning "sort by column 1 in reverse order," which, as currently set, is sorting in reverse order by date/time).
I have simple table that looks like this:
All i need is to SUM points for specific player (John) in his last 3 matches.
I was able to come with this formula:
SUMPRODUCT(LARGE((A2:B="John")*(C2:D);{1;2;3}))
The problem is that instead of what I was looking for, it sums the highest 3 values, that can be anywhere in that range.
Is there some similar formula, that can do only the last 3 matches?
I think a SUMPRODUCT can get you there with some constructed arrays using a COUNTIFS() and ROW() to get the most recent 3.
This formula:
=SUMPRODUCT((COUNTIFS(A:B,G2,ROW(A:B)*{1,1},">="&ROW(A:B)*{1,1})<=3)*(A:B=G2),C:D)
on this sheet I made seems to work.
I thnk I have a formula that gives what you want. It's not pretty, and I'm sure it can be made simpler, but this works:
=query( query(
{ arrayformula( {ROW(A1:A) } ),
query(A1:D,"select A, B, C, D",1)
} , "select * order by Col1 desc",1),
"select Col2, Col3, Col4, Col5
where (Col2 ='John' or Col3 = 'John')
order by Col1 desc limit 3",1)
Basically, it adds the row number as an extra column to the data, so that we can sort the data in reverse order by row number. Then we query the result to find the first three occurences of 'John', in either Col A or Col B.
Here is a sample sheet:
https://docs.google.com/spreadsheets/d/1-mhTb5Cpp3D-1OltlmCfwlmM-vc2OknHxfJAyHD7BjI/edit?usp=sharing
Credit to Erik Tyler for a previous answer on a different question, on how to add the row number to a query.
Edit: Updated the sheet to provide the SUM of John's (or any player's) scores from the last three matches. This can be combined with the previous formula, if you want a single formula to place somewhere. Or will you have a list of all the players, and you'll want their last three scores beside each of their names?
If I can simplify the formula, I'll update it here.
Let me know if you need something more than this, or if this has answered your question.
Approach
I would use the query formula to get the cells that you need so that you can leverage the limit statement.
You should put a column with the indexes so that you can order the cells in descending order and take the first 3.
Given that your table headers are:
+-----------------------------------------------+
| INDEX | NAME 1 | NAME 2 | POINTS 1 | POINTS 2 |
+-----------------------------------------------+
I would use this query to get your desired result:
=SUMPRODUCT(QUERY(A2:E, "Select D * E where B = 'John' or C = 'John'" order by A desc limit 3"))
I'm trying to figure out the way to count the number of Draw for each team.
To count as a draw, a match had to be played (So no empty score value on both cells, and the team must appear in either column B or E, and the result must be "Draw")
Can anyone help me find the proper formulae? I already tried to use COUNTIFS but couldn't succeed.
=QUERY(FILTER({B2:B; E2:E}, {F2:F; F2:F}="Draw"),
"select Col1,count(Col1) group by Col1 label count(Col1)''", 0)
and F2 cell would be:
=ARRAYFORMULA(IF(E2:E<>"",
IF(C2:C=D2:D, "Draw",
IF(C2:C>D2:D, B2:B,
IF(C2:C<D2:D, E2:E, ))), ))
Use Two COUNTIFS() and add them together:
=COUNTIFS(B:B,"Real Madrid",F:F,"Draw")+COUNTIFS(E:E,"Real Madrid",F:F,"Draw")
I have a table with two columns A and B the first is a tag and the second is an amount. I am trying to write a query with two columns, one summing up negative values while the other summing up positive ones.
Coming from SQL, I tried the following
=QUERY(A1:B100,
"SELECT A, SUM( B * IF(B>0, 0, 1) ),
SUM( B * IF(B<0, 0, 1) ) GROUP BY A ")
But it seems that the IF function is not supported in a query. I know I can create two intermediate columns in my sheet (one for positive value and one for negative ones), but I was wondering if it's possible to achieve what I want with a query or somehow without intermediate columns.
If you must use the query function, assuming your Tag Data is in Column A, and your Values in Column B:
=arrayformula(query({A1:A100,if(B1:B100>0,B1:B100,),if(B1:B100<0,B1:B100,)},"Select Col1, sum(Col2), sum(Col3) where Col1 <>'' group by Col1 label Col1 'Tag', sum(Col2) 'Positive', sum(Col3) 'Negative'"))
Here's the example output: https://docs.google.com/spreadsheets/d/1DW5CyPCC71CopW48uKy6basn-WP4hMfh7kuuJXT-C4o/edit#gid=1606239479
=arrayformula(query({a1:a100,if(b1:b100>0,b1:b100,),if(b1:b100<0,b1:b100,)},"Select Col1,sum(Col2),sum(Col3) group by Col1"))
Please see this sheet for an example of using the FILTER function which is probably better than your query function for this use case:
https://docs.google.com/spreadsheets/d/1DW5CyPCC71CopW48uKy6basn-WP4hMfh7kuuJXT-C4o/edit?usp=sharing
I didn't know what you meant by tag, but I just created a list of random words, 10 negative, and 10 positive
With Tags in Column A and Numbers in Column B. Then in Column D I put this for the "positive" filter:
=filter($A$2:$A,$B$2:$B>0)
And for the Positive Sum:
=sum(filter($B$3:$B,$B$3:$B>0))
And in Column E for the Negative filter:
=filter($A$2:$A,$B$2:$B<0)
And for the Negative Sum:
=sum(filter($B$3:$B,$B$3:$B<0))
EDIT: I added another sheet in the workbook that shows you how to list the sum next to each tag in a filtered list of the tags:
On this sheet, I created examples of how to list the total sums of each particular tag: https://docs.google.com/spreadsheets/d/1DW5CyPCC71CopW48uKy6basn-WP4hMfh7kuuJXT-C4o/edit#gid=1784614303
This formula will look at the list of tags/values in Columns A & B, and then match and sum all tags that are in the cell to the left in Column D:
=sum(filter($B$3:$B,$B$3:$B>0,$A$3:$A=D3))