I'm using Google Sheets and using the following formula without any issue:
=QUERY(Sheet!A:D,"select A, max(B) where not B is null group by A label A 'Client', max(B) 'Most Recent'")
Obviously, this is returning columns A and B of the referenced data
However, I would like to also return the corresponding cells from column C.
sample data: https://docs.google.com/spreadsheets/d/1CJKiDNPUWMMUbLLb-UDA6iRA2PBnlMHDsEB9vELe0Rk/edit?usp=sharing
Using this example, what I would like to see is cell G2 populated with "Pizza" (i.e., from C3), and so on.
Am I using the right formula? What do I need to change?
What you are trying to do is not very SQL-like, because max(B) does not point to any particular row: it's just the maximum value of B among the selected rows. This value could be attained by several rows, making the choice of C, D ambiguous. I don't think that a single query can do this.
Here is an implementation with unique and several query commands.
In E2, enter =unique(A:A) to get the list of unique client names.
In F2, enter
=query(A:D, "select B,C,D where A ='"&E2&"' order by B desc limit 1")
and drag this formula down. This selects all rows with the A value matching E2, and picks one with maximal B value.
You don't want to have a header row in the output of these queries so either add label B '', C '', D '' or just don't include the header row in the queried range.
Version with grouping by C,D
To also select C and D within a single query, expand the select clause
select A, max(B), C, D
which will then require including those in the group by clause:
group by A, C, D
The formula will be
=QUERY(A:D,"select A, max(B), C, D where not B is null group by A, C, D label A 'Client', max(B) 'Most Recent'")
This does mean that the only rows to be grouped together will be those where not only A but also C and D are equal.
A possible one-formula solution:
=ArrayFormula(IFERROR(VLOOKUP(UNIQUE(A2:A),SORT(A2:C,2,0),{1,2,3},0)))
Here is what I did that finally worked.
In E1, enter =unique(A:A) to get the list of unique client names. In F2, enter
=query(A$2:D101, "select B,C,D where A ='"&F2&"' order by B desc limit 1")
and drag this formula down. This selects all rows with the A value matching E2, and picks one with maximal B value.
You don't want to have a header row in the output of these queries so just add desired text in header row.
Related
I'm trying to format my budget spreadsheet which updates automatically with an attached form. ColA is hidden since it's a timestamp, ColB is the date that the purchase was made, ColC is the category, and ColD is the amount.
I'm trying to sum all amounts within a category and have the output (in ColD) be sorted in descending order, as well as output the labels next to the amounts (in ColC). I have tried using SUMIF, but it's frustrating to use when I want to add multiple categories in specific ranges together. Here's the current code I'm using:
=QUERY(C3:D64, "SELECT SUM(D) WHERE C <> 'Income' GROUP BY C LABEL SUM(D)''")
This outputs my data, but without the labels and not in descending order. I can make the order descend in ColE with this code, but again, not labeled:
=QUERY(D65:D72, "SELECT D ORDER BY D")
Is there a way to simplify my code and have it output with labels in descending order, including labels for amounts where the output is 0? Here's a screenshot of my current setup.
If you want to include label (Column C), you need to select column C in your query.
Formula order based on column C name in descending order (See Cell F2):
=query(C3:D64,"Select C, sum(D) where C<>'Income' group by C order by C desc label sum(D) ''")
Formula order based on Sum of column D per category in descending order (See Cell I2):
=query(C3:D64,"Select C, sum(D) where C<>'Income' group by C order by Sum(D) desc label sum(D) ''")
You can add labels anyway, but make sure you keep proper order.
1 SELECT
2 WHERE
3 GROUP BY
4 ORDER BY
5 LABEL
(full list of commands is available in [documentation]: 1)
I am not sure what you mean by "Labels" -if you mean categories like "groceries, etc. you should use:
=QUERY(C3:D64, "SELECT C, SUM(D) WHERE C <> 'Income' GROUP BY C ORDER BY SUM (D) LABEL C 'Category', SUM(D) ''")
Sorry if I misanderstood your question
I try to convert one table to another.
What is wrong with my syntax?
=QUERY(B21:D24, "select A,C where A is not null group by A pivot B",1)
Unable to parse query string for Function QUERY parameter 2: CANNOT_GROUP_WITHOUT_AGG
Issue:
CANNOT_GROUP_WITHOUT_AGG
means The query cannot use group columns without a AGGregate function.
select A,C where A is not null group by A pivot B
You're asking it to group by A. If the query groups by Column A, What to do with Column C? Column C cannot be displayed side by side. Although your sample doesn't have duplicates in B, think what will happen, if Column B is a,b,a instead of a,b,c. Column C needs to be aggregated. Said otherwise, For each group in A, What do you want to do with C(if there are multiple items in C for the same group in A)?
Solution:
Provide a Aggregate function for column C like, sum, count,max etc. For each group in A, The corresponding column C will be summed or counted or a max value of C in that group will be taken.
Snippet:
=QUERY(B21:D24, "select A, sum(C) where A is not null group by A pivot B",1)
Please use the following formula to get the 0's as well.
It is the IF function that will give you the 0's in your pivot.
=ArrayFormula(IF(QUERY(M1:O22, "select M, sum(O) where M is not null group by M pivot N")="",0,
QUERY(M1:O22, "select M, sum(O) where M is not null group by M pivot N")))
As for the syntax, it is mentioned that
If you use a pivot clause, then every column listed in the select clause must either be listed in the group by clause, or be wrapped by an aggregation function
Functions used:
ArrayFormula
IF
QUERY
=ARRAYFORMULA({
AVERAGE(QUERY(SPLIT(TRANSPOSE(SPLIT(QUERY(TRANSPOSE(QUERY(TRANSPOSE(
IF(Data!D$2:E856<>"", "♠"&Data!D$2:E856&"♦"&Data!F$2:G856, )),,999^99)),,999^99), "♠")), "♦"),
"select Col2
where lower(Col1) contains '"&LOWER(A2)&"'
offset "&COUNTIF(Data!D$2:E856, A2)-6))})
I have the above formula that I am using. What this does is the following:
The last 6 times A2 shows up in either Column D or E, it accumulates the corresponding value in column F or G. Those 6 values are then turned into an average, as well.
I am trying to add one condition to this. I want it to only take those last 6 instances where column H and I are also something specific.
So when A2 shows up in column D, I only want to use the row if Column I is the value "X". When A2 shows up in column E, I only want to use the row if Column H is "X".
I am unable to get this implemented into my function myself and desperate for some help. One problem is that the "X" search is in reversed column order (ie. when A2 is in D, trying to search I...and when A2 is in E, trying to search G...which isn't the order those appear in the alphabet). Also just not sure where in formula this conditional even needs to go.
Data! just references the sheet I have my dataset dumped into, obviously.
I am able to use the QUERY function to get rows from another sheet but if I try to use ORDER BY I get nothing. Oddly, if I do ORDER BY with DESC it does work.
My example sheet is at https://docs.google.com/spreadsheets/d/18I-GsBzTLtuxwh8sdqeeLb0kLHMc8Z3EpFcN6s17CSU/edit?usp=sharing.
This is my QUERY function that only returns the header row:
=query(source!A:C, "SELECT A, B, C ORDER BY C")
Both of these below work:
=query(source!A:C, "SELECT A, B, C")
=query(source!A:C, "SELECT A, B, C ORDER BY C DESC")
The first one returns all rows and the second one returns all rows sorted on column C.
Am I missing something?
Ordering by C is placing your values at the bottom since the blank cells have a value that places them higher up. For example, if I reduce my rows to only 20 you will see your formula does work, it's just that they are at the bottom:
Try this formula instead: =QUERY(source!,"SELECT A,B,C WHERE A IS NOT NULL ORDER BY C")
That filters out blank cells and should order the value how you are expecting it too.
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))