Google Sheets Query Coalesce? - google-sheets

is there any query syntax that woks like coalesce in google sheets?
if i have a source like pict below
the result i want is only getting id and time if status is true, but the time is only exist in one col either in check column or report column
so the result would be like this...
I tired this but doesn't work
=QUERY(A1:D4, "SELECT A, COALESCE(B, C) WHERE D = TRUE")
any ideas or workarounds?
Thanks

try:
=ARRAYFORMULA(IFERROR(SPLIT(FLATTEN(QUERY(TRANSPOSE(
ARRAY_CONSTRAIN(IF(D2:D=TRUE, {A2:A, IF(B2:C="",,"×"&B2:C), D2:D}, ), 9^9,
COLUMNS(A:C))),, 9^9)), "×")))

A very short one just for the special case of 2 columns where you know that only one of them is populated and they are dates:
=ArrayFormula(to_date(if(D2:D,B2:B+C2:C,)))
Maybe the simplest formula which behaves like coalesce would be
=iferror(if(D2,hlookup(9^9,B2:C2,1,true),))
It's just a pull-down formula but will pick up the first non-blank column from a range of columns containing numbers or dates. If the columns are all blank, it returns blank.

You can take advantage of the either or situation and concatenate the 2 columns.
=filter({A2:A,concat(B2:B,C2:C)},D2:D)
Also see local array and filter

Add a column after Status call it Time (column E), whereas each formula follows this format (assuming your table starts at A3:E)
=if(A4="","",if(B4<>"",B4,C4))
Now query A3:E like so,
=query(A3:E,"Select A,E where D=TRUE")

you can use something like this:
=QUERY(transpose(B1:H1),"Select Col1 where Col1 is not null limit 1",0)
This transposes the row into a column, queries all non-null values from that column, and then set limit 1 to return the first value. So essentially you are selecting the leftmost non-empty value from your row.
I can't take full credit for this, I must have gotten it somewhere else... but it's in one of my sheets.

Related

Finding the first value in a row and getting the address using ArrayFormula

in this example table, I want to get the first "failed" or "passed" from result 1, 2, and 3 column. I already made a formula to get the first mentioned value using:
=IF(C2=C2,CELL("address",INDEX(D2:F2,MATCH(C2,D2:F2,0))),)
which works fine (the column result is from that formula)
But when I'm trying to use ArrayFormula on the formula, it only shows the first row value only. my ArrayFormula is like this:
=ArrayFormula(IF(C2:C4=C2:C4,CELL("address",INDEX(D2:F2,MATCH(C2:C4,D2:F2,0))),))
i think its because the INDEX and MATCH doesn't update as it goes down, any idea how to fix this?
Sheets link: https://docs.google.com/spreadsheets/d/1oFTZHGd9PKpfZ9QXWvTshorEOGFxmD1cpeeQ9bIOYh8/edit?usp=sharing
You could use a query to get the minimum column matching the value in column C for each row in D to F:
=ArrayFormula(lambda(a,address(index(a,,1),index(a,,2)))
(query(split(flatten(if(C2:C="",,if(D2:F=C2:C,row(C2:C)&"|"&column(D2:F),))),"|"),"select Col1,min(Col2) where Col2 is not null group by Col1 label min(Col2) ''")))
Or alternatively you can use a formula similar to your original one with Byrow:
=ArrayFormula(if(C2:C="",,byrow(C2:F,lambda(r,CELL("address",INDEX(r,1+MATCH(index(r,,1),index(r,,2):index(r,,columns(r),0))))))))

Counting the number of times a value appears more than once in a column AND where another conditon is met

Any help in figuring this out would be appreciated. I would like a forumla to calculate the number of times a code number appears more than once AND where type is A.
A sample set of data looks like the following:
In this case the forumla should return 1 as there is one case of a repeated code number (1) where type is (A) - first row and last row in this case.
Would the forumla be any different if I also had a third column and wanted that to be a certain value as well? Again with the test data below I would want this to return 1 in the case that I wanted to measure the number of times any code number appeared more than once where type=A and subtype=C:
.
Ihave started with the following which identifies the number of unique combinations in columns A and B, but I can't seem to add any way to only return where a particular combination appears more than once:
=COUNTUNIQUE(IFERROR(FILTER(A2:A,B2:B="A"),""))
I have tried the following but it doesn't return correctly:
=COUNTUNIQUE(IFERROR(FILTER(A2:A,B2:B="A",COUNTIF(A2:A,A2:A)>1)))
Been trying to figure this one out for a while with no success.
Thank you
You can try this (TABLE = the range corresponding to your dataset, including the header row):
=query(query(transpose(query(transpose(TABLE),,9^9)),"select Col1,count(Col1) where Col1 contains 'A' group by Col1",1),"select Col2-1 where Col2>1 label Col2-1 ''")
What we are doing is to concatenate the Code number & type columns into one using the TRANSPOSE/QUERY/TRANSPOSE...9^9 hack, querying it again to make a temporary table of each group against its count for those groups which meet the criteria, then finally subtracting one from each group count and only returning an answer if there were groups with count>1 to begin with. You will get multiple results if multiple groups satisfy the count>1 criteria.
To add the subtype column to the formula as per the second question, change TABLE to suit, then change the inner QUERY to:
"select Col1,count(Col1) where Col1 contains 'A' and Col1 contains 'c' group by Col1"
Note that the if your 'real' type & subtype categories share characters then the where/contains approach in the QUERY will fail and a different approach will be needed.
Assume that you place you data at A1:B10, what this function do is:
FILTER B1:B10 by type, which is "A" in this example, and return an array which is filtered A1:B10.
Use INDEX to extract only the 1st column, which is the code column of the filtered array, and name it 'DATA' with LAMBDA function.
Use BYROW to iterate 'DATA', and check each code with COUNTIF, if it counts more than one of this code in the filter result, return that code, else return "".
Use UNIQUE to get rid of duplicate results. (since we are looking for code which have more than 1 repeats, so the return array will sure have duplicates.)
Use query to get rid of the extry empty rows.
=QUERY(UNIQUE(
LAMBDA(DATA,
BYROW(DATA,LAMBDA(ROW,
IF(COUNTIF(DATA,ROW)>1,ROW,"")
))
)(INDEX(FILTER(A1:B10,B1:B10="A"),,1))
),"WHERE Col1 IS NOT NULL")
Just noticed that the INDEX function is not necessary, FLITER can directly returns A1:A10 according the compare results of B1:B10.
=QUERY(UNIQUE(
LAMBDA(DATA,
BYROW(DATA,LAMBDA(ROW,
IF(COUNTIF(DATA,ROW)>1,ROW,"")
))
)(FILTER(A1:A10,B1:B10="A"))
),"WHERE Col1 IS NOT NULL")

Why my ArrayFormula is giving error? How do I correct it? (I'm not looking for another Arrayformula as solutions!)

I wanted a ArrayFormula at C1 which gives the required result as shown.
Entry sheet:
(Column C is my required column)
Date Entered is the date when the Name is Assigned a group i.e. a, b, c, d, e, f
Criteria:
The value of count is purely on basis of Date Entered (if john is assigned a on lowest date(10-Jun) then count value is 1, if rose is assigned a on 2nd lowest date(17-Jun) then count value is 2).
The value of count does not change even when the data is sorted in any manner because Date Entered column values is always permanent & does not change.
New entry date could be any date not necessarily highest date (If a new entry with name Rydu is assigned a on 9-Jun then the it's count value will become 1, then john's (10-Jun) will become 2 and so on)
Example:
After I sort the data in any random order say like this:
Random ordered sheet:
(Count value remains permanent)
And when I do New entries in between (Row 4th & 14th) and after last row (Row 17th):
Random Ordered sheet:
(Doesn't matter where I do)
I already got a ArrayFormula which gives the required result:
={"AF Formula1"; ArrayFormula(IF(B2:B="", "", COUNTIFS(B$2:B, "="&B2:B, D$2:D, <"&D2:D)+1))}
I'm not looking for another Arrayformula as solutions. What I want is to know what is wrong in my ArrayFormula? and how do I correct it?
I tried to figure my own ArrayFormula but it's not working:
I got Formula for each cell:
=RANK($D2,FILTER($D$2:$D, $B$2:$B=$B2),1)
I figured out Filter doesn't work with ArrayFormula so I had to take a different approach.
I took help from my previous question answer (Arrayformula at H3) which was similar since in both cases each cell FILTER formula returns more than 1 value. (It was actually answered by player0)
Using the same technique I came up with this Formula which works absolutely fine :
=RANK($D2, ARRAYFORMULA(TRANSPOSE(SPLIT(VLOOKUP($B2, SUBSTITUTE(TRIM(SPLIT(FLATTEN(QUERY(QUERY({$B:$B&"×", $D:$D}, "SELECT MAX(Col2) WHERE Col2 IS NOT NULL GROUP BY Col2 PIVOT Col1", 1),, 9^9)), "×")), " ", ","), 2, 0), ","))), 1)
Now when I tried converting it to ArrayFormula:
($D2 to $D2:$D & $B2 to $B2:$B)
=ARRAYFORMULA(RANK($D2:$D,TRANSPOSE(SPLIT(VLOOKUP($B2:$B, SUBSTITUTE(TRIM(SPLIT(FLATTEN(QUERY(QUERY({$B:$B&"×", $D:$D}, "SELECT MAX(Col2) WHERE Col2 IS NOT NULL GROUP BY Col2 PIVOT Col1", 1),, 9^9)), "×")), " ", ","), 2, 0), ",")), 1))
It gives me an error "Did not find value '' in VLOOKUP evaluation", I figured out that the problem is only in VLOOKUP when I change $B2 to $B2:$B.
I'm sure VLOOKUP works with ArrayFormula, I fail to understand where my formula is going wrong! Please help me correct my ArrayFormula.
Here is the editable sheet link
if I understand correctly, you are trying to "rank" B column based on D column dates in such way that dates are in theoretical ascending order so if you randomize your dataset, the "rank" of each entry would stay same and not change based on the randomness you introduce.
therefore the correct formula would be:
={"fx"; INDEX(IFNA(VLOOKUP(B2:B&D2:D,
{INDEX(SORT({B2:B&D2:D, D2:D}, 2, 1),,1),
IFERROR(1/(1/COUNTIFS(
INDEX(SORT(B2:D, 3, 1),,1),
INDEX(SORT(B2:D, 3, 1),,1), ROW(B2:B), "<="&ROW(B2:B))))}, 2, 0)))}
{"fx"; ...} array of 2 tables (header & actual table) under each other eg. ;
outer shorter INDEX or longer ARRAYFORMULA (doesnt matter which one) is needed coz we are processing an array
IFNA for removing possible #N/A errors from VLOOKUP function when VLOOKUP fails to find a match
we VLOOKUP joint B and D column B2:B&D2:D in our virtual table {} and returning second 2 column if there is an exact match 0
our virtual table {INDEX(SORT({B2:B&D2:D, D2:D}, 2, 1),,1), ...} we VLOOKUP from is constructed with 2 columns next to each other eg. ,
we are getting the first column by creating an array of 2 columns {B2:B&D2:D, D2:D} next to each other where we SORT this array by date/2nd column 2, in ascending order 1 but all we need after sorting is the 1st column so we use INDEX where we bring all rows ,, and the first column 1
now lets take a look on how we getting the 2nd column of our virtual table by using COUNTIFS which will mimic the "rank"
IFERROR(1/(1/ is used to remove all zero values from the output (all empty rows would have 0 in it as the "rank")
under COUNTIFS we put 2 pairs of arguments: "if column is qual to column" and "if row is larger or equal to next row increment it by 1" ROW(B2:B), "<="&ROW(B2:B))
for "if column is qual to column" we do this twice and use range B2:D and sort it by date/3rd column 3 in ascending order 1 and of this we again need only the 1st column so we INDEX it and return all rows ,, and first column 1
with this formula you can add, remove or randomize your dataset and you will always get the right value for each of your rows
as for why your formula doesnt work... to not get #N/A error for vlookup you would need to define the end row of the range but still, the result wont be as you would expect coz formula is not the right one for this job.
as mentioned there are functions that are not supported under AF like SUM,AND,OR and then there are also functions which work but in a different way like IFS or with some limitations like SPLIT,GOOGLEFINANCE,etc.
I have answered you on the tab in your shared sheet called My Practice thusly:
You cannot split a two column array as you have attempted to do in cell CI2. That is why your formula does not work. You can only split a ONE column array.
I understand you are trying to learn, but attempting to use complicated formulas like that is going to make it harder I'm afraid.

How to refer to column 'BY' in query?

In my Google spreadsheet, i'm using the query function to get data from one sheet onto another. The query looks something like this:
=QUERY('mySheet'!$A$1:100,"select F where "&C$3&"='myValue'")
This works fine until cell C3 has value "BY" (because the word "by" has significance in the query language). I've tried using single quotes, but then the query uses header "BY" instead of column BY and it returns an empty result.
Any ideas on how to work around this?
Put it in backticks.
=sum(QUERY(select `BY` where `BY` is not null limit 7))
This will sum the first 7 values in column BY.
(This was fun to debug. The formula worked in every other column...)
"BY" is a special word. It is present in clause group by
You may use this:
=QUERY({'mySheet'!$A$1:100},"select Col5 where Col"&C$3&"='myValue'", 0)
and paste the column number into C$3
see more info here
BTW you may use function column() to know BY is column 77 or find the right number by header name: =match("column name", 'mySheet'!1:1, 0)

Google Sheets - Query - Running Total below dynamic results

Testing Sheet:
Wondering if there is a witty way to add a Total to the last row +1 of
a Query result.
See Sheet 'Lookup' for a static example of what I am asking for.
I don't know if there is a way to have a hidden column that calculates
transposed only under the last row of a query, or if there is a smart
way to work Query for this answer.
All great answers. Each on very useful in its use case.
Макс Махров gets the answer with using a query statement.
Now I was not keen on having an extra sheet to hold the totals so I added a row at the top which I can simply hide and used this formula:
query({Orders!A:E;A1:E1},"select Col1, Col3, Col4 where Col2 = '"&C3&"' order by Col4",1)
Only problem I have is trying to figure out how to add TEXT to the bottom row, it seems to only want numerical input.
How do I fix this? What am I glitching?
Thanks !
Mars
The trick is to make second query and count totals for selected product.
Plan of actions:
add new sheet with query on it, something like this: =QUERY(Orders!A:E,"select B, 0, sum(D) where B like '"&Lookup!C2&"' Group by B",0)
Prepare arrayformula which combines data in Lookup sheet: = ArrayFormula({Importrange(1),Importrange(2)}) Note that number of columns must retain the same.
Edit query so it takes Col1, Col2, Col3... instead of A, B, C...
Make word 'total' visible instead of zero. Set number format: 0;0;total Set it for range B9:B on Lookup sheet
Make Conditional Formatting with formula =and($B4 =0,isnumber($B4)) for range A4:C on Lookup sheet.
That's seems have to complete the task.
Hope it Helps!
Your Example
Working example.
Here is one way:
Put TOTAL way down in row 1000
Select the range A3:C999. Select data > filter to create filters
Select C3, set the filter to hide all blanks
A second way is to limit the query result to show only the top 8 results:
Change your query to =query(Orders!A:E, "select A, C, D where B = '"&C2&"' order by D desc limit 8",1) It will reverse-order column D (largest first), and set row limit to 8.
Change the formula of your TOTAL to =sumif(Orders!B:B,C2,Orders!D:D)
Try this formula in the column adjacent to your query:
=ArrayFormula({$C$4:offset($C$4,count($C$4:$C),0,1,1);sum($C$4:offset($C$4,count($C$4:$C),0,1,1))})
It duplicates your column of values (I haven't figured out a way around that yet) and then adds a total to the bottom of that column, and changes dynamically with the range from your query.
Here's a working version.
Interesting challenge! It got the old grey matter turning... ;)
Thanks,
Ben

Resources