How does the "=QUERY()" function work in Google Sheets, i.e. what does it do? I have read this post, but still don't fully understand...
QUERY is something like FILTER on steroids because it can aggregate (sum, count, min, max, avg) stuff and also pivot stuff grouping the dataset eg. mimicking UNIQUE. also as the only function there it can understand strings/text input as commands for example:
A1: 2+3
A2: =QUERY(, "select "&A1)
QUERY is also able to understand the concept of header rows. and lastly, we can abuse QUERY to concatenate stuff in any direction because JOIN and TEXTJOIN does now work under ARRAYFORMULA
see more QUERY magic at: stackoverflow.com/q/65435313
Related
I have a Google Sheet with named ranges that extend beyond columns A-Z. The name ranges have header rows. I would like to use the QUERY function to select columns by their header labels.
My formula is like this:
=QUERY(NamedRange,"SELECT AZ, AX, BM where BB='student' ORDER BY BM DESC",1)
Answers to other questions on StackOverflow, like that accepted here, haven't worked. Another answer found here on Google's support page doesn't work for columns beyond Z.
How can I use the QUERY function and select columns beyond column AA by their header labels?
DESIRED OUTPUT / SAMPLE DATA
A sample spreadsheet with desired output can be found here.
you can transpose it and header row becomes a column. then:
=TRANSPOSE(QUERY(TRANSPOSE(A1:C), "where Col1 matches 'bb header|student'", ))
where A1:C is your named range (including header row)
update:
=QUERY({AI1:AK6}, "select Col2,Col3 where Col1='Jones'", 1)
dynamically:
=LAMBDA(p, t, s, QUERY({AI1:AK6},
"select Col"&t&",Col"&s&"
where Col"&p&"='Jones'
order by Col"&t&" desc", 1))
(MATCH("principal", AI1:AK1, ),
MATCH("teacher", AI1:AK1, ),
MATCH("student", AI1:AK1, ))
WHY LAMBDA ?
LAMBDA is a regular GS function that allows substituting any type of ranges with custom strings. generic example of simple lambda: =LAMBDA(x, x+5)(A1) which is in old terms: =A1+5 therefore you can understand it as x being a placeholder for A1. one more example: =IF((A1+1)>(B1+1), B1+1-A1+200, B1+1*A1+20) contains a lot of repeating cell references so we can refactor it like: =LAMBDA(a, b, IF((a+1)>b, b-a+200, b*a+20))(A1, B1+1) this comes especially handy with more advanced formula stacking when instead of repeating the whole fx multiple times we can wrap it in Lambda to shorten it and make it cleaner
you can have as many LAMBDAs as you wish:
here, just for fun, one more example... with lambda:
and without lambda: pastebin.com/raw/BREgC9La
(from: stackoverflow.com/a/74380299/5632629)
You can try the below Named Function I created a while ago. Import from here
Name
_BETTERQUERY
Usage example
=_BETTERQUERY(A1:C10,"select `name` where `age` > 18",1)
Formula description
Runs a Google Visualization API Query Language query across data. It supports the usage of column headers.
Argument placeholders
range
better_query
headers
Formula definition
=QUERY({range},REGEXREPLACE(REDUCE(better_query,
REGEXEXTRACT(better_query,REGEXREPLACE(REGEXREPLACE(better_query,
"([()\[\]{}|^.+*$?])","\\$1"),"`(.*?)`","`($1)`")),LAMBDA(acc,cur,
SUBSTITUTE(acc,cur,"Col"&MATCH(cur,ARRAY_CONSTRAIN(range,1,9^9),0),1))),
"`(Col\d+)`","$1"),headers)
Notes
This function is built on top of QUERY, so you can use it exactly as QUERY. When referring to the columns with their header, make sure that the first row of range is the header and in better_query enclose the column header between two backticks `col_header`. (See example usage above)
The headers parameter is not optional since Named Functions do not currently allow optional parameters.
If you want to understand more about how this works. See How to Use Column Names in QUERY
I'm working with the following Google Sheet.
Sheet2 uses the following QUERY() function to retrieve data from Sheet1
=QUERY(IMPORTRANGE("1s8krJ7rbZ1DMblZ3vdLcG5pySVM3ESCBy1o7R5Zv4LM", "Sheet1!B3:D"))
Is it possible to return the Row Totals (For Example: B4+C4+D4 for Row 4) using the above QUERY() function?
Please Advise.
My Query and Expected Output are Outlined on the Google Sheet.
You should be able to do something like this:
=QUERY(IMPORTRANGE("1s8krJ7rbZ1DMblZ3vdLcG5pySVM3ESCBy1o7R5Zv4LM", "Sheet1!B3:D"), "Select Col1+Col2+Col3 label Col1+Col2+Col3 ''")
Note that importing from another tab in the same spreadsheet doesn't require importrange. In that case, this should also work:
=QUERY(Sheet1!B3:D, "Select B+C+D label B+C+D ''")
Another way, to achieve the same result would be
=ArrayFormula(if(len(Sheet1!B3:B), Mmult(--Sheet1!B3:D, transpose(column(Sheet1!B2:D2)^0)),))
Be aware that while a simple QUERY can return the results, it will actually take up the entire column if you don't limit it. In other words, all the null rows from Sheet1! B:D will also come over with the QUERY. If you want only the results that have numbers, try something like this:
=QUERY(Sheet1!B3:D, "Select B+C+D WHERE B+C+D is not null label B+C+D ''")
Or you could use MMULT like this:
=MMULT(FILTER(Sheet1!B3:D,Sheet1!B3:B<>""),SEQUENCE(3,1,1,0))
The results may look the same whether limited or not. But in a QUERY or MMULT without limitations, you won't be able to use the space below the visible results for anything. I only mention this because, currently in your sheet, you do have data (a TRANSPOSE formula) below the main results. If you won't in your real sheet and don't care about the are below the visible results being inaccessible to other data or formula entry, then you don't need to limit.
I am using Google Sheets and I need to implement following excel formula into my sheet.
https://docs.google.com/spreadsheets/d/1XzAYEezt2gNt_tdbxyZT-p6XwjNdhvUbt_9rBoABlhI/edit?usp=sharing
=IFERROR(INDEX(Formularantworten!B:B;AGGREGAT(15;6;ROW(Formularantworten!$B$2:$B$100)/(Formularantworten!$B$2:$B$100<>"")/(Formularantworten!$H$2:$H$100<>"");ROW(A1)));"")
Well if you want to match two columns and index a third column, finding the first match, you can do what you used to do in Excel before Aggregate came along:
=index(C:C,match(1,(A:A<>"")*(B:B<>""),0))
or
=index(C:C,min(if((A:A<>"")*(B:B<>""),row(A:A))))
But in Google sheets you have more options and are more likely to use something like
=query(A:C,"select C where A is not null and B is not null limit 1")
I'm using FILTER to extract rows from a range, and want to take only certain columns. For example, I filter by D, but want only columns B,C in reverse order. I tried to use QUERY:
=QUERY(filter(B:D,D:D>=2), "select C,B") - Error: can't analyze query string for function QUERY parameter 2: NO_COLUMNC
=QUERY(filter(B:D,D:D>=2), "select *") - shows me all columns, so QUERY should work...
How do I QUERY the results of FILTER? Any other way to achieve this?
When you are QUERYing a computed array, you need to use the Colx notation rather than column letters:
=QUERY(FILTER(B:D,D:D>=2),"select Col2, Col1")
which incidentally can be achieved by just using the QUERY:
=QUERY(B:D,"select C, B where D >= 2")
or just FILTER:
=FILTER({C:C,B:B},D:D>=2)
Although using the Query function is simple and straight-forward. There's another way to achieve this output using the Filter function
You can nest the original FILTER function inside another FILTER function and specify an array of 1's and 0's mentioning which column you need and which you don't.
=Filter( FILTER(B2:E6,D2:D6>10900) , {1,0,0,1} )
How about using arrays on the go?
=FILTER({B:B, D:D},D:D>=2)
In this way you select columns in place, and they won't change if new column would be added.
Does anybody know how to arrayformula this join function?
My formula is not as complex as the example here. ArrayFormula a Filter in a Join (Google Spreadsheets)
It does not contain a filter function, so I'm not sure what from that answer applies and doesn't apply.
I want to array formula this: =if(isblank(B2),,join("," ,B2:I2))
Using the normal way to array something doesn't work:
=ArrayFormula(if(isblank(B2:b),,join(",",B2:b:I2:i)))
Also for splits, I have split(B2, ",")
=ArrayFormula(split(B2:B,",")) does nothing but the first row
Maybe try:
=ArrayFormula(if(len(B2:B), B2:B&C2:C&D2:D&E2:E&F2:F&G2:G&H2:H&I2:I,))
or
=ArrayFormula(substitute(transpose(query(transpose(B2:I),,rows(B2:B)))," ",""))
or, in case you want a space between the concatenated values:
=ArrayFormula(trim(transpose(query(transpose(B2:I),,rows(B2:B)))))
For using split() in arrayformula a workaround can be found here