How to query(traverse) along a wide format table? - google-sheets

I have a table like that.
I can't get my head around how to traverse(query selectively) through the countries and output data per date. Sometimes I need one country, sometimes 3 or 5.
I just need to have a separate table where I'll have something like that for later processing (charts and other calculations).
Usually, I'd use something like
=QUERY(A1:100, "SELECT a column WHERE a row ='Name of a country'")
or
=TRANSPOSE(QUERY(A1:100, "Select * WHERE A = 'Australia'"))
But it looks like this logic doesn't work here. Any ideas?
Here is a dummy sheet
P.S.
The second Cumulative column it's just an example of calculations that I'll need to do later with each country numbers. I'll just add =iferror(B3+C2,"0") Although if you have any better ideas on how to optimise that, I'll be happy to hear it.

try:
=QUERY(TRANSPOSE(QUERY(TRANSPOSE(Sheet4!A:AQ),
"where Col1 matches 'Date|Australia|India'", 0)),
"where Col1 >= "&DATEVALUE("2020-1-23")&"
and Col1 <= "&DATEVALUE("2020-1-30"), 1)
and the cumulatives (running totals) can be done like:
=ARRAYFORMULA(IF(O3:O="",,SUMIF(ROW(O3:O), "<="&ROW(O3:O), O3:O)))

Related

In Google Sheet, how do you use SUMIFS with OR logic matching a list of items?

In order to clarify the scenario, please check the example here:
https://docs.google.com/spreadsheets/d/1E_xyPvkTIObG5JA4UfG1EQa74cFEc9QiznidJ4HSmEY/edit?usp=sharing
What I want to do here is to:
filter by date (matching a certain date)
filter by product id (matching a list of specified ids)
sum up the total
I did try to find some ideas, though none of them worked, including the solution in the article below
https://exceljet.net/formula/sumifs-with-multiple-criteria-and-or-logic
Really appriciate if someone could point me in the right direction, thanks!
use:
=QUERY({'raw data'!A2:C},
"select Col1,sum(Col3)
where Col2 matches '"&TEXTJOIN("|", 1, 'ids to match'!A2:A)&"'
group by Col1
order by Col1 desc
label sum(Col3)''")
Sumifs is different than Sumif. You also have some text mixed with numbers. Your dates are text while Column b is numeric. Try this:
=Sumifs(C:C:,A:A,"2022-09-08",B:B,82267,B:B,82602) +
Sumifs(C:C:,A:A,"2022-09-08",B:B,82267,B:B,82602B:B,82604)
As Player() points out, if you have too many products to include, using sumifs would get pretty tedious and you ought to consider using a different function (i'd use filter). However since your question was Sumifs related, that's your answer.
To illustrate how this would work with something Filter, you could do this:
=sum(filter('raw data'!C:C,('raw data'!A:A=A2)*
(isnumber(match('raw data'!B:B,'ids to match'!A:A,0)))))

Formatting and organizing time entries in Google Sheets

I have tables with Start and End time data entered in either an AM/PM cell for each day in this spreadsheet. How do I organize and display the number of hours between the two times to end up with a graph that looks like the second image below?
Starting data
Desired data
Challenges/variables:
Data is provided in free text so it may not be in a time format. Usually it is 1, 2, 4 or 5 characters but it might be anywhere from 1 -5 characters with some variations depending on the use of a colon. For example, 1, 10, 130, 1:30, 1130, 12:30.
My approach
IF(RIGHT(B2,2)="AM",text(IF(AND(LEN(C2)>0,LEN(C2)<3),
C2&":00",IF(LEN(C2)>3, C2, "")), "HH:MM AM/PM"),
IF(RIGHT(B2,2)="PM",text(IF(AND(LEN(C2)>0,LEN(C2)<3), 12+C2&":00",IF(LEN(C2)>3,
12+split(C2,":")&":"&RIGHT(C2,2), "")), "HH:MM AM/PM"),""))
I used length to figure out if something was already in a time format, and convert those that weren't. I added 12 to any PM value. If it was blank, it would result in a blank space.
Limitations:
I couldnt get it to work as an array (not sure why)
I realized afterwards that this would not work for 3 or 4 characters where there was no colon Entries like 1120, 145 wont work, for example 7:00 - 1120 = 7:00.
Possible solutions?
1.I think probably a REGEX would work better to convert anything into a time format but other solutions would be possible such as seeing if the 3rd character from the Right was equal to :
2. As far as the reorganization, I think it will require some combination of filter, transpose, or query, but I think a prerequisite might be getting the conversion to work as an array of some sort.
Thanks in advance for your help. The shared spreadsheet is here.
You'll have to add in some more if new time formats are added, but give this a swing
=ARRAYFORMULA(
TRANSPOSE(
QUERY(
QUERY(
IF(ISBLANK(C2:C),,
{A2:A,REGEXEXTRACT(B2:B,"(.*) \|"),
IF(REGEXMATCH(TO_TEXT(C2:C),"AM|PM"),C2:C,
IF(REGEXMATCH(TO_TEXT(C2:C),":"),--(TEXT(C2:C,"HH:MM")&" "&RIGHT(B2:B,2)),
IF(LEN(C2:C)<3,--(C2:C&":00 "&RIGHT(B2:B,2)),
--(REGEXREPLACE(TO_TEXT(C2:C),TO_TEXT(RIGHT(C2:C,2)),"")&":"&RIGHT(C2:C,2)&" "&RIGHT(B2:B,2)))))}),
"select Col1, Max(Col3)
where
Col3 is not null and
Col1 is not null
group by Col1
pivot Col2
label Col1 'Day'
format Max(Col3) 'hh:mm am/pm'"),
"select Col1, Col3, Col2")))
I also added your duration difference to your sheet.
=ARRAYFORMULA(
IF(ISBLANK(H9:J9),,
IF(H11:J11<=H10:J10,
1+H11:J11-H10:J10,
H11:J11-H10:J10)))
The ranges will be different, depending on where you have it. It would be best to remove the TRANSPOSE from the first formula so the days run down the column. I included a demo of this in your sheet.
see:
=ARRAYFORMULA(IF(ISNUMBER(C2:C15)*(IFERROR(TIMEVALUE(C2:C15), 2)<=1), TIMEVALUE(C2:C15),
IF(ISNUMBER(C2:C15)*(IFERROR(TIMEVALUE(C2:C15), 2)=2),
IFERROR(TIMEVALUE(C2:C15&":00 "&REGEXEXTRACT(B2:B15, "AM|PM")),
TIMEVALUE(REGEXREPLACE(C2:C15&"", "(\d+)(\d{2})$", "$1:$2 ")&REGEXEXTRACT(B2:B15, "AM|PM"))),)))

Only apply complex arrayformula() to rows with certain value in dataset

I have a quite complext formula (i mean that is complex to me) that Tom Sharpe helped me building to aggregate values and ordering them by months in a row(you can find the details in the original post but i think you'll only need the final formula which is:
=ArrayFormula(mmult(sequence(1,counta(A2:A),1,0), if((C2:index(C:C,counta(C:C))<=eomonth(G2,sequence(1,datedif(G2,H2,"M")+1,0)))* (D2:index(D:D,counta(D:D))>=eomonth(G2,sequence(1,datedif(G2,H2,"M")+1,0))),E2:index(E:E,counta(E:E)),0)))
and here is the result -> [J1:U1]
Now, what i would need to do as the final step is to be able to group data by a certain label (John or Jane in the example) on separate rows, but mantaining the order/aggregate by month on the row. On the example, this would mean having one row with only 'John' data and below, one with 'Jane' values.
I am struggling to understand how to adapt the formula to do so.
I have tried:
Using another array to first return a list of these labels with query(unique()) or something like that, but then i struggle looping in it with the other formula.
A bit more simplistic but it could work after all: on the 1st row (the cell next to where the data will be returned) writing 'John', on row 2 'Jane' and then using filter() to only pull data that matches. The 'John, Jane' value is for the example but the real labels won't be that many, the list of labels don't need to be dynamic.
The thing with these solutions is that they work when used separately, but i can't figure out how to nest this in the first arrayformula() that Tom helped me with...As i am just beginning with the google sheets queries.
I don't really need necessarily the complete formula/code but maybe just directions or tips to visualize the way i could solve this.
Thanks to all who might contribute
With hindsight I might have done better to go down the route of using a query to calculate the sums on my previous answer rather than Mmult.
This uses the same method as before to create a 2d array of amounts vs dates (going across) and individuals (going down). Then it uses Textjoin to generate a query to group by name with the required number of columns.
=ArrayFormula(query({A2:A,if((C2:C<=eomonth(G2,sequence(1,datedif(G2,H2,"M")+1,0)))* (D2:D>=eomonth(G2,sequence(1,datedif(G2,H2,"M")+1,0))),E2:E,0)},
"select Col1,sum(Col"&textjoin("),sum(Col",,sequence(1,datedif(G2,H2,"M")+1,2))&") where Col1 is not null group by Col1"))
This is the generated query
select Col1,sum(Col2),sum(Col3),sum(Col4),sum(Col5),sum(Col6),sum(Col7),sum(Col8),sum(Col9),sum(Col10),sum(Col11),sum(Col12),sum(Col13) where Col1 is not null group by Col1
Ideally there should be an extra section saying label sum(Col2) '' etc. to suppress the 'Sum' headers.
=ArrayFormula(query({A2:A,if((C2:C<=eomonth(G2,sequence(1,datedif(G2,H2,"M")+1,0)))* (D2:D>=eomonth(G2,sequence(1,datedif(G2,H2,"M")+1,0))),E2:E,0)},
"select Col1,sum(Col"&textjoin("),sum(Col",,sequence(1,datedif(G2,H2,"M")+1,2))&") where Col1 is not null group by Col1 label sum(Col" & textjoin(") '', sum(Col",,sequence(1,datedif(G2,H2,"M")+1,2)) & ") ''"))

IMPORTRANGE: value missing?

I have been working on this issue for a few weeks now and can't seem to find a solution. I used this answer (IMPORTRANGE with CONDITIONS) to get as far as I could, but I keep getting a value error.
This is the sheet I'm working with.
My goal is to use the first tab in the sheet (All Games) to enter all the games that I come across to create a compendium. But, then I want it to automatically populate the other tabs based on certain criteria (what type of game, skills learned, etc.)
On the Warm-Ups tab you'll see the formulas I have tried. A1 is the most recent.
Here is the formula I tried:
=QUERY(IMPORTRANGE("https://docs.google.com/spreadsheets/d/1F64PMg_iFu-DaJAUaE4BkpqF4zoteknp56VfwAUe8ag/edit#gid=1359689553", "All Games!A1:A1300"),"SELECT Col1 WHERE (Col2 = 'w') ")
I am getting a value error:
Unable to parse query string for Function QUERY parameter 2: NO_COLUMN: Col2
you are trying to reference Col2 but you selected range A1:A1300 which is just 1 column. therefore try:
=QUERY(IMPORTRANGE("1F64PMg_iFu-DaJAUaE4BkpqF4zoteknp56VfwAUe8ag", "All Games!A1:B1300"),
"SELECT Col1 WHERE (Col2 = 'w') ")
from the brief look on your sheet, you may want use matches or contains instead of = in your QUERY
You are only importing (part of) ColumnA - so no wonder Google can't find a second column :)

How to concatenate strings and select the same columns multiple times using Query (Google Sheets)

I am trying to generate a table for the Gantt chart. Table should have this format:
https://developers.google.com/chart/interactive/docs/gallery/ganttchart#data-format
So,I need task name the same like taks ID, but in Query I can't use Col1 twice (I get error)
=QUERY({Tab1;Tab1};"select Col1,Col1,Col5,Col16,Col17 WHERE Col16>now() ORDER BY Col5 DESC,Col17 ";0)
The second point is that it is also not possible to merge two columns as a result, so it doesn't work:
=QUERY({Tab1;Tab1};"select Col1+Col7,Col1,Col5,Col16,Col17 WHERE Col16>now() ORDER BY Col5 DESC,Col17 ";0)
Here is my data and 2 results what I neet to get by QUERY
https://docs.google.com/spreadsheets/d/1CZYgfYo6oIeONZOH6ZR5rOW615HuH4ICaoe7lj0dapw/edit#gid=0
These are such trivial things in a real SQL, is there no way to do it somehow straightforwardly in Google Query? So far I have found a combination of QUERY and ARRAYFORMULA but then there are very complicated queries - mutants. Not easier?
You don't need Query, just Arrays.
You will get the first result from this code:
={ARRAYFORMULA(B3:B&" "&C3:C)\A3:A}
The second result from this code:
={A3:A\A3:A\B3:B1}
Based on your example I assume that you are not using US spreadsheet settings.
If so formulas have to be change to:
First:
={ARRAYFORMULA(B3:B&" "&C3:C),A3:A}
Second:
={A3:A,A3:A,B3:B}
Link to working example: https://docs.google.com/spreadsheets/d/1eMkOkyFwvDeYSy-8UlhQum4OWcb-4WJqGxy_CXM8pVs/edit?usp=sharing
I see that in your real sheet you would like to compare some data with now(). You can easily do this using array I propose as a source to Query. There will you have something like this (of course now it will not work - its only an example - an array have only 2 columns, not 15):
=QUERY({ARRAYFORMULA(B3:B10&" "&C3:C10)\A3:A10};"select * where Col15>now()";0)
About Query - you can't perform arthmetic operations on column containing strings. Look at the documentation: https://developers.google.com/chart/interactive/docs/querylanguage#arithmetic-operators
"I can't use Col1 twice (I get error)"
You can duplicate your indata that to solve this.
QUERY({Tab1 Column 1\Tab1 Column 1};"Select Col1, Col2......"
"Tab1 Column 1" is now Col1 and Col2
"The second point is that it is also not possible to merge two columns as a result, so it doesn't work:"
Yes, adding result of column is possible "select Col1+Col7......" is correct.

Resources