I have a simple table of characters, their gender and stats.
Character
Gender
Strength
Constitution
Agility
Alice
F
15
10
7
Bob
M
10
15
8
Charlie
F
8
14
5
Dylan
M
9
9
17
I wanted to make a Best 3 table basing on some criteria, eg.
Best 3, Strength:
No.
All
Female
Male
1
Alice
Alice
Bob
2
Bob
Charlie
Dylan
3
...
...
...
To get the strongest among all people I simply use:
=LARGE(C2:C5;1)
To get the strongest among females I know I need something like:
=IF(COUNTIFS({B2:B5};"F");LARGE(C2:C5;1))
Where {B2:B5} is a range of the "Gender" column, C2:C5 is a range for "Strength" column. But this gives me the value from the "Strength" column (15), and I need a corresponding value from the "Character" column (Alice). I don't know how to nest another function that will give me the corresponding name.
I would also be grateful if the function would give all the names that match the criterion, eg. if there was Elliot with strength 15, his name should be displayed along with Alice. But I have no clue how to ever approach this problem.
For the top 3 'All' try
=query(A2:E5, "Select A where B <>'' order by C desc limit 3", 0)
and you can use the same logic for the top 3 'Male'
=query(A2:E5, "Select A where B = 'M' order by C desc limit 3", 0)
and 'Female'
=query(A2:E5, "Select A where B = 'F' order by C desc limit 3", 0)
See if that works for you?
Reference
Query()
Related
I have a spreadsheet that looks like this, which tracks attendance and order. On day 1, the order was [Alice, Bob, Catherine, Dave]. On day 2, the order was [Bob, Dave, Catherine], and Alice was absent:
Date
Alice
Bob
Catherine
Dave
10/1
0
1
2
3
10/2
x
0
2
1
10/3
3
1
2
0
10/4
1
0
x
x
10/5
0
x
1
2
I am trying to write a formula to get the total number of times each attendee went last. In other words, I want to count the number of times a name in a column is the MAX value for each date row, ignoring any x's. Ideally, I would like a single formula that I could place in a single cell. If successful the resulting table would look like this:
Attendee
# of times they went last
Alice
2
Bob
0
Catherine
1
Dave
2
What's the best way to accomplish this?
Find the MAX BYROW, then compare the max to each of the Attendees using REDUCE+OFFSET. If equal, create a SUM:
=LAMBDA(
max,
REDUCE(
{"Attendee","#times"},
B1:E1,
LAMBDA(
a,c,
{a;c,SUMPRODUCT(OFFSET(c,1,0,5)=max)}
)
)
)(BYROW(B2:E6,LAMBDA(r,MAX(r))))
try:
=INDEX(QUERY(BYROW(B2:INDEX(E:E, MAX((A:A<>"")*ROW(A:A))),
LAMBDA(x, TEXTJOIN(, 1, IF(x=MAX(x), B1:E1, )))),
"select Col1,count(Col1) group by Col1 label count(Col1)''"))
with Bob:
=SORTN({QUERY(BYROW(B2:INDEX(E:E, MAX((A:A<>"")*ROW(A:A))),
LAMBDA(x, TEXTJOIN(, 1, IF(x=MAX(x), B1:E1, )))),
"select Col1,count(Col1) group by Col1 label count(Col1)''");
TRANSPOSE({B1:E1;(B1:E1="")*1})}, 9^9, 2, 1, 1)
One easy way is to add a column with the name of the last attendee. If, when you say you want a single formula, the reason is to don't show other cells, you can hide the column. Then you count how many times each name appears. This should be the result:
Date
Alice
Bob
Catherine
Dave
last
Attendee
# of times they went last
10/1
0
1
2
3
Dave
Alice
2
10/2
x
0
2
1
Catherine
Bob
0
10/3
3
1
2
0
Alice
Catherine
1
10/4
1
0
x
x
Alice
Dave
2
10/5
0
x
1
2
Dave
Formula in cell G2 (under "last"), copied to the other cells of the column:
=INDEX(B$1:E$1,1,MATCH(MAX(B2:E2), B2:E2, 0))
It searches, only in that line, the maximum value. Gets the column and returns the correspondent name from the first line.
Formula in I2 (under "Attendee"):
=TRANSPOSE(B1:E1)
Transposes all names from the first line to the column.
Formula in J2, copied to the other cells of the column:
=COUNTIF(G$2:G,I2)
Counts how many times the name appears in column G.
Feels like this may be a basic, but I cannot find a way to do this with sumifs.
I've got four columns in one table, representing the workload of an employee like this:
Job
Employee # 1
Employee # 2
Workload
Job 1
Bob
Jane
5
Job 2
Bob
2
Job 3
Jane
Susan
3
Job 4
Susan
2
I'd like to output total workflow results to a second sheet for each employee based on a specialized formula. In English, the forumla would be:
Calculate the total workload for each employee.
- For each job that includes that includes employee named "X" and no assigned teammate, use the job's corresponding workload value.
- For each job that includes that includes employee named "X" and has an assigned teammate, reduce the corresponding workload value by 50%.
So with the given table above, I'd want an output like this:
Employee Name
Workload
Bob
4.5
Jane
4
Susan
3.5
Math:
Bob = ((job_1 / 2) + job_2)
Jane = ((job_1 / 2) + (job_3 / 2))
Susan = ((job_3 / 2) + job_4)
Does anyone know how I can accomplish this?
Functions like sumifs seem to only let me set criteria to sum or not sum a value. But I cannot find a clear way to sum only 50% of a value based on a condition in a separate column.
=LAMBDA(name,SUMIFS(D2:D5,B2:B5,name,C2:C5,"")+SUMIFS(D2:D5,B2:B5,name,C2:C5,"<>")/2+SUMIFS(D2:D5,C2:C5,name)/2)("Bob")
The math is
SUM D, if B is Bob and C is empty and
SUM half of D if B is Bob and C is not empty and
SUM half of D, if C is Bob.
Or the same logic via query:
=QUERY(
{
QUERY(B1:D5,"Select B,sum(D) where C is null group by B");
QUERY(B1:D5,"Select C,sum(D)/2 where C is not null group by C");
QUERY(B1:D5,"Select B,sum(D)/2 where C is not null group by B")
},
"Select Col1, sum(Col2) where not Col1 contains 'Employee' group by Col1"
)
However, note that we're assuming title contains Employee and no other names contain Employee.
Employee # 1
sum sum Workload
Bob
4.5
Jane
4(Incorrect in the question)
Susan
3.5
Use this formula
=ArrayFormula({ "Employee Name", "Workload";
QUERY(
QUERY({LAMBDA(a,b,c,d,k, {b,a,{d/k};c,a,{d/k}} )
(A2:A,B2:B,C2:C,D2:D,
BYROW(B2:C, LAMBDA(c, IF(COUNTA(c)=0,,IF(COUNTA(c)=1,1,2)))))},
"Select (Col1),sum(Col3) Group by Col1" ,0), "Where Col1 <> '' ",0)})
Used formulas help
ARRAYFORMULA - QUERY - LAMBDA - BYROW - IF - COUNTA - SUM
Say I have a table with two columns: name and age, and that the table's rows are ordered by age.
I need a function to find the name of the youngest person who is at least 50 years old.
Example
For this list:
Name
Age
Nordom
3
Annah
19
Ignus
56
Morte
72
We'd get "Ignus".
As you said age column is sorted so can try below formula.
=INDEX(FILTER(A2:A5,B2:B5>=50),1)
Try this:
=query(B3:C,"select B,C where C > "&E3&" order by C limit 1")
If you want just Ingus with no headers and age, you can do:
=query(B3:C,"select B where C > "&E3&" order by C limit 1",0)
use:
=QUERY(A:B; "select A where B >= 50 limit 1")
Suppose I have a table like so:
one
ID
three
a
2
one
b
7
two
c
6
three
a
9
four
b
3
five
c
1
six
a
5
seven
b
10
eight
c
8
nine
a
4
ten
I want to GROUP BY one, get MAX of ID and then get the associated value from three.
I can do the first part like so:
=QUERY(A1:C11, "SELECT A, MAX(B) GROUP BY A")
To get:
one
max ID
a
9
b
10
c
8
But I want to get:
one
max ID
three
a
9
four
b
10
eight
c
8
nine
I am trying to do this all with one QUERY. I know I could use a VLOOKUP for the 3rd column but I'm hoping there is way to do with one QUERY.
From the Query Language Reference documentation, it is explicity stated in the rules of the GROUP BY clause that every column in the SELECT must be a grouped column -or- wrapped by an aggregation function. This is why it is not possible to include an ungrouped, unaggregated column in your specific query.
You can do the workaround as per player0's answer, but if you want to use QUERY() andVLOOKUP() in a single formula you can use this as well:
=ARRAYFORMULA({{QUERY(A1:C,"SELECT A, max(B) where A is not null group by A")},{VLOOKUP(FILTER(F:F,LEN(F:F)),SORT(B1:C,1,TRUE),2)}})
Sample:
This should also work. You can & the columns together pre-query, then split them out afterwards.
=ARRAYFORMULA(QUERY(SPLIT(QUERY({A:A,TEXT(B:B,"000000000")&"|"&C:C&"|"&A:A},"select MAX(Col2) where Col1<>'' group by Col1",1),"|"),"select Col3,Col1,Col2"))
use:
=SORTN(SORT(A2:C, 2, 0), 9^9, 2, 1, 1)
update:
={QUERY(source!A:E,
"select B,C,max(A) where D is not null group by B,C", 1),
{"value"; ARRAYFORMULA(IF(INDEX(QUERY(QUERY(source!A:E,
"select B,C,max(A) where D is not null group by B,C", 1),
"offset 1", 0),,1)<>"",
VLOOKUP(INDEX(QUERY(QUERY(source!A:E,
"select B,C,max(A) where D is not null group by B,C", 1),
"offset 1", 0),,3), source!A:E, 5, 0), ))}}
Was curious why Formula 2 (below) doesn't work, i.e. returns just a zero and not an array whereas Formula 1 works (below). The argument construction seems is similar.
DM:DM is list of employers. (not unique employers, i.e. Bob post several jobs)
DW:DW is # of positions offered for a particular job.
DU:DU is type of job.
DM DW DU
Bob 3 Sales
Alice 10 Cashier
Mike 4 Clerk
Bob 1 Sales
I think the issue is the way I am using the "Unique" function nested inside countifs vs. sumifs and wrapping this inside an arrayformula. In Formula 1, the array returns number of job posts for unique employer, and so Bob 2, Alice 1, Mike 1. What I was attempting in Formula 2 was Bob 4, Alice 10, Mike 4. I could accomplish this by separating multiple columns and functions but I wondered if anyone knew of an elegant way to do this using arrayformula so I have it in one column. Thanks and I hope this question was clear.
Formula 1
=arrayformula(countifs('Data (QC)'!DM:DM,UNIQUE('Data (QC)'!DM:DM),'Data (QC)'!DU:DU,"Shop Sales Assistant"))
Formula 2
=arrayformula(sumifs('Data (QC)'!DW:DW,'Data (QC)'!DM:DM,unique('Data (QC)'!DM:DM),'Data (QC)'!DU:DU,"Shop Sales Assistant"))
=arrayformula ( unique ({filter( Log!M2:M, Log!M2:M<>"" ), sumif ( filter ( Log!M2:M, Log!M2:M<>"" ), "=" & filter ( Log!M2:M, Log!M2:M<>"" ), Log!W2:W )}))
try:
=QUERY(A2:C, "select A,sum(B) where A !='' group by A label sum(B)''", 0)
and for count:
=QUERY(A2:C, "select A,count(B) where A !='' group by A label count(B)''", 0)