Combining SUMIF and SUMPRODUCT statements - excel-2010

I have two separate formulas that work, but I’m having trouble combining them.
A B
Alex 50000
Alex 200000
John 50000
I want to sum the values in column B for numbers that are equal to and greater than 50000 but less than 100000 only for where Alex appears in column A.
=SUMIF(A2:A4,"Alex",B2:B4)
=SUMPRODUCT((B2:B4>=50000)*(B2:B4<100000),B2:B4)
Any assistance would be appreciated.
Thanks!

This only requires SUMPRODUCT.
Just always maintain the pattern:
SUMPRODUCT(
(ConditionRange1=Condition1)*
(ConditionRange2=Condition2)*
(ConditionRange3=Condition3)*
(ValueRange))
So, in your example:
SUMPRODUCT(
(B2:B4>=50000)*
(B2:B4<100000)*
(A2:A4="Alex")*
(B2:B4))
SUMPRODUCT will now evaluate the conditions of every row with either 0 or 1, take the product per row and sum it up. (And if theres one time 0, the row results in 0, which does not Change the final sum):
A B >=50000 < 100000 "Alex" RowProduct
Alex 50000 1 1 1 1*1*1*50000 = 50000
Alex 200000 1 0 1 1*0*1*200000 = 0
John 50000 1 1 0 1*1*0*50000 = 0
--------
50000

Related

List all numbers between 0 and 10^n containing repdigits in google sheets

In Google sheets How to get a list of all repdigits numbers between 0 and 10^n.
Example: We have the input n in B1 set to 3 therefore our numbers are between 0 and 10^3 alternatively between 0 and 1000
We should get this list of repdigits.
11,22,33,44,55,66,77,88,99,111,222,333,444,555,666,777,888,999
Requirments
Less references
Shortest formula
Efficient processing
If possible without lambda and its helpers
Note
If cell or row/column limit is reached is acceptable not to join the result.
More examples
n
Output
3
11,22,33,44,55,66,77,88,99,111,222,333,444,555,666,777,888,999
4
11,22,33,44,55,66,77,88,99,111,222,333,444,555,666,777,888,999,1111,2222,3333,4444,5555,6666,7777,8888,9999
5
11,22,33,44,55,66,77,88,99,111,222,333,444,555,666,777,888,999,1111,2222,3333,4444,5555,6666,7777,8888,9999,11111,22222,33333,44444,55555,66666,77777,88888,99999
6
11,22,33,44,55,66,77,88,99,111,222,333,444,555,666,777,888,999,1111,2222,3333,4444,5555,6666,7777,8888,9999,11111,22222,33333,44444,55555,66666,77777,88888,99999,111111,222222,333333,444444,555555,666666,777777,888888,999999
7
11,22,33,44,55,66,77,88,99,111,222,333,444,555,666,777,888,999,1111,2222,3333,4444,5555,6666,7777,8888,9999,11111,22222,33333,44444,55555,66666,77777,88888,99999,111111,222222,333333,444444,555555,666666,777777,888888,999999,1111111,2222222,3333333,4444444,5555555,6666666,7777777,8888888,9999999
8
11,22,33,44,55,66,77,88,99,111,222,333,444,555,666,777,888,999,1111,2222,3333,4444,5555,6666,7777,8888,9999,11111,22222,33333,44444,55555,66666,77777,88888,99999,111111,222222,333333,444444,555555,666666,777777,888888,999999,1111111,2222222,3333333,4444444,5555555,6666666,7777777,8888888,9999999,11111111,22222222,33333333,44444444,55555555,66666666,77777777,88888888,99999999
9
11,22,33,44,55,66,77,88,99,111,222,333,444,555,666,777,888,999,1111,2222,3333,4444,5555,6666,7777,8888,9999,11111,22222,33333,44444,55555,66666,77777,88888,99999,111111,222222,333333,444444,555555,666666,777777,888888,999999,1111111,2222222,3333333,4444444,5555555,6666666,7777777,8888888,9999999,11111111,22222222,33333333,44444444,55555555,66666666,77777777,88888888,99999999,111111111,222222222,333333333,444444444,555555555,666666666,777777777,888888888,999999999
10
11,22,33,44,55,66,77,88,99,111,222,333,444,555,666,777,888,999,1111,2222,3333,4444,5555,6666,7777,8888,9999,11111,22222,33333,44444,55555,66666,77777,88888,99999,111111,222222,333333,444444,555555,666666,777777,888888,999999,1111111,2222222,3333333,4444444,5555555,6666666,7777777,8888888,9999999,11111111,22222222,33333333,44444444,55555555,66666666,77777777,88888888,99999999,111111111,222222222,333333333,444444444,555555555,666666666,777777777,888888888,999999999,1111111111,2222222222,3333333333,4444444444,5555555555,6666666666,7777777777,8888888888,9999999999
11
11,22,33,44,55,66,77,88,99,111,222,333,444,555,666,777,888,999,1111,2222,3333,4444,5555,6666,7777,8888,9999,11111,22222,33333,44444,55555,66666,77777,88888,99999,111111,222222,333333,444444,555555,666666,777777,888888,999999,1111111,2222222,3333333,4444444,5555555,6666666,7777777,8888888,9999999,11111111,22222222,33333333,44444444,55555555,66666666,77777777,88888888,99999999,111111111,222222222,333333333,444444444,555555555,666666666,777777777,888888888,999999999,1111111111,2222222222,3333333333,4444444444,5555555555,6666666666,7777777777,8888888888,9999999999,11111111111,22222222222,33333333333,44444444444,55555555555,66666666666,77777777777,88888888888,99999999999
12
11,22,33,44,55,66,77,88,99,111,222,333,444,555,666,777,888,999,1111,2222,3333,4444,5555,6666,7777,8888,9999,11111,22222,33333,44444,55555,66666,77777,88888,99999,111111,222222,333333,444444,555555,666666,777777,888888,999999,1111111,2222222,3333333,4444444,5555555,6666666,7777777,8888888,9999999,11111111,22222222,33333333,44444444,55555555,66666666,77777777,88888888,99999999,111111111,222222222,333333333,444444444,555555555,666666666,777777777,888888888,999999999,1111111111,2222222222,3333333333,4444444444,5555555555,6666666666,7777777777,8888888888,9999999999,11111111111,22222222222,33333333333,44444444444,55555555555,66666666666,77777777777,88888888888,99999999999,111111111111,222222222222,333333333333,444444444444,555555555555,666666666666,777777777777,888888888888,999999999999
Repdigits are multiples of Repunits like 11, 111. We can easily create Repunits of 1 by REPeaTing 1 and supplying a SEQUENCE to number of times argument of REPT. Once created, just multiply them by sequence of 1..9 and JOIN them using ,.
Snippet(for 3):
=ARRAYFORMULA(TEXTJOIN(",",,REPT("1",SEQUENCE(3-1,1,2))*SEQUENCE(1,9)))
This question could phrased like:
How to get all repdigit, monodigit or numbers that consist of the same digit between 0 and 10^n
Use this formula
=ArrayFormula(
LAMBDA(n, REGEXEXTRACT(TEXTJOIN(",",1,BYROW(SEQUENCE(n), LAMBDA(r, TEXTJOIN(",",1,REPT(SEQUENCE(9),r))))),"11.+"))
(B1))
Explanation
We are repeating each number in the sequence {1;2;...n} 1,2,...n times and joining with comma , and join all with comma ,.
In other words:
For each number in {1;2;...n} REPT once and twice and ... n times then join all with a comma.
Used formulas help
ARRAYFORMULA - LAMBDA - REGEXEXTRACT - TEXTJOIN - BYROW - SEQUENCE - REPT
not sure how serious you are with n but try:
={""; INDEX(QUERY(FLATTEN(QUERY(TRANSPOSE(REPT(
SEQUENCE(1, 9), SEQUENCE(C1, 1, 2))&","),,9^9)),,9^9))}
where C1 = 1000 -----> (10^1000)
and if you are brave enough, change 1000 to 10000 or 50000 :)

Sheets ArrayFormula. Find nearest number by group

Master Data
Group-Value pairs
1 | 1
1 | 2
1 | 3
2 | 5
2 | 8
3 | 10
3 | 12
Work Data
Group-Value pairs + desired result
1 | 4 | 3 (3≤4, max in group 1)
1 | 2 | 2 (2≤2, max in group 1)
2 | 6 | 5 (5≤6, max in group 2)
3 | 7 | no result (both 10 and 12 > than 7)
The task is to find the maximum possible matched number from a group, the number should be less or equal to the given number.
For Group 1, value 4:
=> filter Master Data (1,2,3) => find 3
Will have no problem with doing it once, need to do it with arrayformula.
My attempts to solve it were using modifications of the vlookup formula, with wrong outputs so far.
Samples and my working "arena":
https://docs.google.com/spreadsheets/d/11Cd2BGpGN-0h2bL0LQ_EpIDBKKT2hvTVHoxGC6i8uTE/edit?usp=sharing
Notes: no need to solve it in a single formula, because it may slow down the result.
I used
=ArrayFormula(VLOOKUP(D4:D8&text(E4:E8,"0000"),A4:A10&text(B4:B10,"0000"),1,true))
starting in J4
then
=ArrayFormula(if(--left(J4:J8)=D4:D8,--right(J4:J8,4),""))
starting in K4.
Needs further refinement but doesn't make any assumptions about max of previous group.
EDIT
So after further work it would look like this
=ArrayFormula(if(D4:D="",,
if(D4:D=
vlookup(D4:D&text(E4:E,"0000"),filter({A4:A&text(B4:B,"0000"),A4:A},A4:A<>""),2,true),
vlookup(D4:D&text(E4:E,"0000"),filter({A4:A&text(B4:B,"0000"),B4:B},A4:A<>""),2,true),"")))
A lot like #player0's solution in fact.
I guess you could make it a bit more general by doing something like
=text(B4,rept("0",ceiling(log10(max(B4:B)))))
assuming these are positive integers.
Alternative method
I think this is a better way. Find the start row of each group and how many rows r less than or equal to the required group/value pair are in that group. Then just go forward r-1 rows from the first line of the group to find the matching value:
=ArrayFormula(if(countifs(A4:A,D4:D,B4:B,"<="&E4:E)>0,
vlookup(
vlookup(D4:D,{A4:A,row(A4:A)},2,false)+countifs(A4:A,D4:D,B4:B,"<="&E4:E)-1,{row(A4:A),B4:B},2,false),))
Assuming of course that the Master data is sorted by group and value - otherwise you would have to use sort():
=ArrayFormula(if(countifs(A4:A,D4:D,B4:B,"<="&E4:E)>0,
vlookup(
vlookup(D4:D,{sort(A4:A,A4:A,1,B4:B,1),row(A4:A)},2,false)+countifs(A4:A,D4:D,B4:B,"<="&E4:E)-1,{row(A4:A),SORT(B4:B,A4:A,1,B4:B,1)},2,false),))
My solution was based on the technique of finding the maximum number by a row. The sample formula is here:
https://docs.google.com/spreadsheets/d/1VY157ykKsCVDqEKDBp3oAVaG0LTXAz8wUCggCrFXMDM/edit#gid=628408999
My whole solution is here:
https://docs.google.com/spreadsheets/d/11Cd2BGpGN-0h2bL0LQ_EpIDBKKT2hvTVHoxGC6i8uTE/edit#gid=0
Step 1
Get joined numbers by groups from a Master Table.
1 | 3,2,1
2 | 8,5
3 | 12,10
Used offset to achieve this ↑. And used vlookup to match this semi-result with work table.
Step 2
Used if + split to check if the resulted value was ≤ than my work value, and in the same formula used query to find the maximum by each row.
compose a query: used join + sequence
=IF(M3=0,,"select "&JOIN(", ",INDEX("max(Col"&SEQUENCE(M3)&")")))
result:
select max(Col1), max(Col2), max(Col3), max(Col4), max(Col5)
Found the maximum by each group:
=index(TRANSPOSE(QUERY(TRANSPOSE(data), "select ...")))
This final formula was the 🔑 to solving the problem.
Note: the result: 0 of my formula means "no matches". This is fine for me.
try:
=INDEX(IFNA(IF(E4:E>=
VLOOKUP(D4:D&TEXT(E4:E, "00000"), {A4:A&TEXT(FILTER(B4:B, B4:B<>""), "00000"), B4:B}, 2),
VLOOKUP(D4:D&TEXT(E4:E, "00000"), {A4:A&TEXT(FILTER(B4:B, B4:B<>""), "00000"), B4:B}, 2), 0)))

Create single formula for several different lines (array) (Google Sheets)

In the AD column I have this sequence of values:
2
3
4
These values refer to rows in a column on another page.
In each line in AE column I use this formula:
=IF(AD1="","",IFERROR(SUM(FILTER(INDIRECT("'Registro Geral'!O2:O"&AD1)/100,REGEXMATCH(INDIRECT("'Registro Geral'!H2:H"&AD1),SUBSTITUTE(SUBSTITUTE(JOIN("|",$V$1:$V$4),"||",""),"|||",""))=TRUE))))
=IF(AD2="","",IFERROR(SUM(FILTER(INDIRECT("'Registro Geral'!O2:O"&AD2)/100,REGEXMATCH(INDIRECT("'Registro Geral'!H2:H"&AD2),SUBSTITUTE(SUBSTITUTE(JOIN("|",$V$1:$V$4),"||",""),"|||",""))=TRUE))))
=IF(AD3="","",IFERROR(SUM(FILTER(INDIRECT("'Registro Geral'!O2:O"&AD3)/100,REGEXMATCH(INDIRECT("'Registro Geral'!H2:H"&AD3),SUBSTITUTE(SUBSTITUTE(JOIN("|",$V$1:$V$4),"||",""),"|||",""))=TRUE))))
In short, this formula is getting a running Sum of values in the other sheet based on whether or not the corresponding cell in another column of the same sheet appears in a set of values.
When I try to add ARRAYFORMULA so that I don't have to have a formula on each line, leaving only in AE1, the values that return on all lines are exactly the same value.
Test Formula Fail:
=ARRAYFORMULA(IF(AD1:AD="","",IFERROR(SUM(FILTER(INDIRECT("'Registro Geral'!O2:O"&AD1:AD)/100,REGEXMATCH(INDIRECT("'Registro Geral'!H2:H"&AD1:AD),SUBSTITUTE(SUBSTITUTE(JOIN("|",$V$1:$V$4),"||",""),"|||",""))=TRUE)))))
Link to Spreadhseet example:
https://docs.google.com/spreadsheets/d/1qIv6KnLv-EwJQXRrk7ucuqY-XuJhkIHOCtih9FpAg6U/edit?usp=sharing
You're trying to do a running summation on O based on whether the corresponding value in the H column appears in the Filtered values.
We can do this with a matrix multiplication using a lower-triangular matrix and the listed values, selecting which ones to zero out based on certain conditions using IF.
=ArrayFormula(MMULT(
N(SEQUENCE(D2)>=SEQUENCE(1,D2)),
ARRAY_CONSTRAIN(
IF(
('Registro Geral'!O2:O<>"")*
IFNA(MATCH('Registro Geral'!H2:H,V:V,0)),
'Registro Geral'!O2:O
)/100,
D2,
1
)
))
Why this works
The lower-triangular matrix looks like
1 0 0 0 0 ... up to N columns
1 1 0 0 0
1 1 1 0 0
1 1 1 1 0
1 1 1 1 1
... up to N rows
The Column you want to sum looks like
Value 1
Value 2
...
Value N
So when you multiply the two, you get a new matrix of dimension N x 1:
Value 1
Value 1 + Value 2
...
Value 1 + ... + Value N
If we don't want to sum a value, then we can zero it out with a conditional so that it never gets added.

Looping through a set of google sheet values

I have 2 sets of data. One is tank names
Tank Name
A1
A2
B1
B2
and the next is ON/OFF Data
ON/OFF
0
1
1
1
1
1
0
0
1
1
1
1
1
1
1
0
0
1
1
1
0
1
1
Now the result I am looking is, when the ON/OFF is 1 then the first tank is to be mentioned: when it's 0, no tank to be mentioned. Once all the tanks are mentioned,then it should again start from the first tank ie A1.But if 0 comes in between then it should start again from A1 .. like this
Result expected
0
1 A1
1 A2
1 B1
1 B2
1 A1
0
0
1 A1
1 A2
1 B1
1 B2
1 A1
1 A2
1 B1
0
0
1 A1
1 A2
1 B1
0
1 A1
1 A2
You can check the google sheet here : Scenario 2 https://docs.google.com/spreadsheets/d/1SP2SfA-bzzhHgfrvpyUIkeQfUykata0oHxyD-x69yxE/edit?usp=sharing
Hope to get some help to get this solved.
Thanks
Edit
Single formula solution:
=FILTER(IF(B1:B=0,"",VLOOKUP(IFERROR(VLOOKUP(SUMIF(ROW(B1:B),"<="&ROW(B1:B),B1:B),{ROW(INDIRECT("a1:a"&COUNTIF(B:B,1))) , TRANSPOSE(SPLIT(TEXTJOIN("",1,TRANSPOSE(TEXT(ROW(INDIRECT("a1:a"&MAX(LEN(SPLIT(TEXTJOIN("",1,B1:B),"0")))))*(LEN(SPLIT(TEXTJOIN("",1,B1:B),"0"))>=ROW(INDIRECT("a1:a"&MAX(LEN(SPLIT(TEXTJOIN("",1,B1:B),"0")))))),"0"","";;"))),",")) },2,),0),{row(INDIRECT("a1:a"&COUNTIF(B1:B,1))) , VLOOKUP(MOD(ROW( INDIRECT("a1:a"&COUNTIF(B1:B,1)) )-1,COUNTA(A1:A))+1,{ROW(A1:A)-row(A1)+1,A1:A},2,)},2,)),B1:B<>"")
Two formulas will do it.
#1 in C1. For cumulative sum with a loop:
=Filter(IFERROR(VLOOKUP(SUMIF(ROW(B1:B),"<="&ROW(B1:B),B1:B),{ROW(INDIRECT("a1:a"&COUNTIF(B:B,1))) , TRANSPOSE(SPLIT(TEXTJOIN("",1,TRANSPOSE(TEXT(ROW(INDIRECT("a1:a"&MAX(LEN(SPLIT(TEXTJOIN("",1,B1:B),"0")))))*(LEN(SPLIT(TEXTJOIN("",1,B1:B),"0"))>=ROW(INDIRECT("a1:a"&MAX(LEN(SPLIT(TEXTJOIN("",1,B1:B),"0")))))), "0"","";;"))),",")) },2,),0),B1:B<>"")
#2 in D1. For the result:
=FILTER(IF(B1:B=0,"",VLOOKUP(C1:C,{row(INDIRECT("a1:a"&COUNTIF(B1:B,1))) , VLOOKUP(MOD(ROW( INDIRECT("a1:a"&COUNTIF(B1:B,1)) )-1,COUNTA(A1:A))+1,{ROW(A1:A)-row(A1)+1,A1:A},2,)},2,)),B1:B<>"")
References:
Counters Lab
Array Formulas Lab
You can do it most easily with a helper column
=if(B4=1,if(B3=0,0,mod(E3+1,4)),"")
starting in E4 then
=if(E4<>"",index(A$4:A$7,E4+1),"")
starting in F4.
Here's one way of doing it with a single non-array formula:
=IF(B4=1,INDEX(A$4:A$7,MOD(SUM(B4:INDEX(B:B,MAX(INDEX(IF(B$4:B4=0,ROW(B$4:B4)),0)),0))-1,4)+1),"")
in (say) G4 and pulled down.
NB both of these assume that the sequence in column B starts with a zero and would need adjustment if this is not the case.
An array formula is also possible:
=ArrayFormula(if(B4:B=1,vlookup(mod(sumif(row(B4:B),"<="&row(B4:B),B4:B)-sumif(row(B4:B),"<="&vlookup(row(B4:B),if(B4:B=0,row(B4:B)),1),B4:B)-1,4)+4,{row(4:7),A4:A7},2,false),""))
EDIT
Probably the easiest way to get it to work when the first row of on/off data contains a 1 is to include the header row in column B and use n() to treat it as zero so the helper column formula is
=if(B4=1,if(n(B3)=0,0,mod(E3+1,4)),"")
and the non-array formula is
=IF(B4=1,INDEX(A$4:A$7,MOD(SUM(B4:INDEX(B:B,MAX(INDEX(IF(n(B$3:B4)=0,ROW(B$3:B4)),0)),0))-1,4)+1),"")
The array formula works without any change. This is for the fortuitous reason that, while the second Vlookup will fail with #N/A if there are no zeroes in column B before the current row, when this is passed to Sumif you get a zero result which is what you need.

influxdb query basic percentage calculation

I want calculate a division between a number of values different form zero in a specific table and the number of value equal to zero in the same table
SELECT (count("value") WHERE value = 0 / count("value") WHERE value != 0) * 100 FROM "ping_rtt" WHERE time < now() - 15
Obviously this is wrong and I was wondering what could me the correct way to structure the query.
If your field value consists of just zeros or ones; you can easily calculate percentage as:
SELECT 100*sum(value)/count(value) from your_metric
Or simply use Mean function instead of count/sum.
But if value consists of any arbitrary numbers; there is a tricky way (based on this fact that current InfluxDB implementation calculates zero/zero as zero) to achieve this :) You can first map your field value to zeros and ones and then calculate percentage:
SELECT 100*count(map_value)/sum(map_value) FROM (SELECT value/value as map_value FROM your_metric)
It works properly in my influxdb 1.6.0; suppose there is a metric called metric which contain a field val as:
> select * from metric
name: metric
time tag val
---- --- ---
1539780859073434500 15
1539780862064944400 10
1539780865272757400 7
1539780867449546100 0
1539780880145442700 -8
1539781131768616600 12 0
1539781644977103800 12 0.5
1539781649113051900 12 1.5
as you can see, there are different float number as 0,-8,1.5,0.5 and so on.
we can now map our val field to zero or one:
> select val/val as normal_val from metric
name: metric
time normal_val
---- ----------
1539780859073434500 1
1539780862064944400 1
1539780865272757400 1
1539780867449546100 0
1539780880145442700 1
1539781131768616600 0
1539781644977103800 1
1539781649113051900 1

Resources