Google Sheets Pivot Table: MIN and MAX within a group - google-sheets

I have the following source data in Google sheets
Date
Place of Stay
1-Sep
Miami
2-Sep
Miami
3-Sep
Miami
4-Sep
Marathon
5-Sep
Key West
6-Sep
Key West
7-Sep
Miami
8-Sep
N/A
Using this, I've constructed the following pivot table:
Place of Stay
Check-in
Check-out
Miami
1-Sep
8-Sep
Marathon
4-Sep
5-Sep
Key West
5-Sep
7-Sep
For the "Check-in" field, I simply took a MIN of the Date field. The "Check-out" is a "calculated field" which does a =MAX('Date')+1.
However, this is not the desired pivot table output that I want to see, because this looks like I'm checking into Miami on 9/1 and only checking out on 9/8 where in reality, I'm checking into Miami again on 9/7 and checking out on 9/8.
So the ideal output I'd like to see is
Place of Stay
Check-in
Check-out
Miami
1-Sep
4-Sep
Marathon
4-Sep
5-Sep
Key West
5-Sep
7-Sep
Miami
7-Sep
8-Sep
So every time the place of stay changes, I need a new entry in the pivot table which indicates a check-in and checkout.
Any idea how to achieve this? Thanks in advance.

Create a group with such a formula (it is possible to find an arrayformula)
=if(B2=B1,C1,C1+1)
and then perform a pivot table. https://docs.google.com/spreadsheets/d/1P_NlIf4r4LlXuj8FDn-AcSlUYSK6hwqbOoyrq-0KU5E/edit?usp=sharing

Related

How to check for overlapping dates

I am looking for a solution on either Google sheets or app script to check for overlapping dates for the same account. There will be multiple accounts and the dates won't be in any particular order. Here is an example below. I am trying to achieve the right column "check" with some formula or automation. Any suggestions would be greatly appreciated.
Start Date
End Date
Account No.
Check
2023-01-01
2023-01-02
123
ERROR
2023-01-02
2023-01-05
123
ERROR
2023-02-25
2023-02-27
456
OK
2023-01-11
2023-01-12
456
OK
2023-01-01
2023-01-15
789
ERROR
2023-01-04
2023-01-07
789
ERROR
2023-01-01
2023-01-10
012
OK
2023-01-15
2023-01-20
012
OK
I also found some similar past questions, but they don't have the "for the same account" component and/or requires some sort of chronological order, which my sheet will not have.
How to calculate the overlap between some Google Sheet time frames?
How to check if any of the time ranges overlap with each other in Google Sheets
Another approach (to be entered in D2):
=arrayformula(lambda(last_row,
lambda(acc_no,start_date,end_date,
if(isnumber(match(acc_no,unique(query(query(split(flatten(acc_no&"|"&split(map(start_date,end_date,lambda(start_date,end_date,join("|",sequence(1,end_date-(start_date-1),start_date)))),"|")),"|"),"select Col1,count(Col2) where Col2 is not null group by Col1,Col2",0),"select Col1 where Col2>1",1)),0)),"ERROR","OK"))(
C2:index(C2:C,last_row),A2:index(A2:A,last_row),B2:index(B2:B,last_row)))(
counta(A2:A)))
Briefly, we are creating a sequence of dateserial numbers between the start & end dates for each row, doing some string manipulation to turn it into a table of account number against each date, then QUERYing it to get each account number which has dateserials with count>1 (i.e. overlaps), using UNIQUE to get the distinct list of those account numbers, then finally matching this list against the original list of account numbers to give the ERROR/OK output.
(1) Here is one way, considering each case which could result in an overlap separately:
=ArrayFormula(if(A2:A="",,
if((countifs(A2:A,"<="&A2:A,B2:B,">="&A2:A,C2:C,C2:C,row(A2:A),"<>"&row(A2:A))
+countifs(A2:A,"<="&B2:B,B2:B,">="&B2:B,C2:C,C2:C,row(A2:A),"<>"&row(A2:A))
+countifs(A2:A,">="&A2:A,B2:B,"<="&B2:B,C2:C,C2:C,row(A2:A),"<>"&row(A2:A))
)>0,"ERROR","OK")
)
)
(2) Here is the method using the Overlap formula
min(end1,end2)-max(start1,start2)+1
which results in
=ArrayFormula(if(byrow(A2:index(C:C,counta(A:A)),lambda(r,sum(text(if(index(r,2)<B2:B,index(r,2),B2:B)-if(index(r,1)>A2:A,index(r,1),A2:A)+1,"0;\0;\0")*(C2:C=index(r,3))*(row(A2:A)<>row(r)))))>0,"ERROR","OK"))
(3) Most efficient is to use the original method of comparing previous and next dates, but then you need to sort and sort back like this:
=lambda(data,sort(map(sequence(rows(data)),lambda(c,if(if(c=1,0,(index(data,c-1,2)>=index(data,c,1))*(index(data,c-1,3)=index(data,c,3)))+if(c=rows(data),0,(index(data,c+1,1)<=index(data,c,2))*(index(data,c+1,3)=index(data,c,3)))>0,"ERROR","OK"))),index(data,0,4),1))(SORT(filter({A2:C,row(A2:A)},A2:A<>""),3,1,1,1))
HOWEVER, this only checks for local overlaps. not globally. You can see what I mean if you change the dataset slightly:
Clearly the first and third pair of dates have an overlap but G4 contains "OK". This is because each pair of dates is only checked against the adjacent pairs of dates. This also applies to the original reference cited by OP - here's an example where it would give a similar result:
The formula posted by #The God of Biscuits gives the correct (global) result :-)

Google Sheets - Trick to have flexible ARRAYFORMULA

first time posting here!
I have the following scenario:
1 Google Sheet with information sorted in tables (Master Data)
1 Google Sheet that =Importrange the data from the Master Data Google Sheet.
I need to import one time, or multiple times, some of the rows that are Imported from the Master Data based on the following criteria:
On the Master Data Google Sheet, a column would be present, showing in which Country/Countries the student lives. If the student lives 1 country, import the row once. If it is in 2,3,4... countries, import the same row it 2,3,4... times.
Right now, I am using the following formula:
=QUERY({IMPORTRANGE(Reference!A8,Reference!$A$2&Reference!B6)},"select Col6 where Col10='"&'Advanced Settings'!B5&"'")
This formula Imports from the Master Data file (Reference!A8), a particular tab (Reference!$A$2) and a particular range in this tab Reference!B6. Finally, it filters the data imported (only the 6th Col of the range, and only if on Col 10 the row has a particular value (Advanced Settings'!B5).
Is there a way to Import the name of the student as many times as countries they live in inside the same Array formula?
Right now, I am just adding more importrange (if there are 3 countries, I will add Importrange three times) with filters, but I would like to make it dynamic for the number of countries, without manual input every time. Also, the number of students imported varies every time so I can't look manually at the number of rows and then add a formula after the last cell of the array formula.
Thanks!
EDIT:
Sample Data and expected result:
Sample Data
Student Name
Gender
Class Level
Home State
Country
Alexandra
Female
4. Senior
CA
UK, US
Andrew
Male
1. Freshman
SD
UK
Anna
Female
1. Freshman
NC
UK, US
Becky
Female
4. Senior
SD
US
Benjamin
Male
4. Senior
WI
UK
Filter on both Class Level (4. Senior) and Country
Name
Reason for appearing (explanation for you)
Alexandra
Appears because Alexandra is Senior, UK
Alexandra
Appears because Alexandra is Senior, US
Becky
Appears because Becky is Senior, US
Benjamin
Appears because Benjamin is Senior, UK
The expected result here is that Alexandra appears twice as she's Senior and both US and UK.
if Reference!B6 is a range and IMPORTRANGE for each country is the same try:
=QUERY({IMPORTRANGE(Reference!A8, Reference!A2&Reference!B6)},
"select Col6
where Col10 matches '"&TEXTJOIN("|", 1, 'Advanced Settings'!B5:B)&"'", )
IF C = Senior and E is splittable, create a array of corresponding As. Then, FLATTEN the array and REDUCE to remove all empty items in the array.
Sample:
=ARRAYFORMULA(
REDUCE(
"Senior List",
FLATTEN(
IF(
C2:C6="4. Senior",
IF(ISTEXT(SPLIT(E2:E6,",")),A2:A6,),
)
),
LAMBDA(a,c,IF(c="",a,{a;c}))
)
)

Sorting and removing non-duplicate rows in google sheet and keeping non-duplicate rows and duplicate rows

I am fairly new to Google sheets, and essentially what I am trying to do is remove all non-duplicate values that do not exist or is listed in another sheet or row - and also store the non-duplicate values somewhere else
In my example sheet here, I am trying to only keep the Alcohol names that are listed in column G
So in my case, I only want to keep the following records:
Alcohol Name Alcohol Type Origin
Martell Cognac France
Captain Morgans Rum Jamaica
Wray & Nephew Rum Jamaica
Hennessey Cognac France
Barcardi Rum Cuba
Courvoiser Cognac France
Famous Grouse Scotch Scotland
Jack Daniels Whisky USA
Grants Scotch Scotland
Ciroc Vodka France
I also want to keep any that did not appear in the list in a separate table like this:
Alcohol Name Alcohol Type Origin
Russian Standard Vodka Russia
Southern Comfort Bourbon USA
Ciroc Whisky France
At the moment I am having to manually check a longer list one by one and it is taking lot of time and my arm hurts..
If someone can please help me with sorting it such that it looks like this, would be great! I don't know if there are formulas we can use
Use this formula to only keep the Alcohol names that are listed in column G
=QUERY(A1:C," where A matches '"&TEXTJOIN("|",1,G2:G)&"' ",1)
To order them use
=QUERY(A1:C," where A matches '"&TEXTJOIN("|",1,G2:G)&"' order by A",1)
Use this to keep any that did not appear in the list in a separate table.
You see, you only put not in the formula
=QUERY(A1:C," where not A matches '"&TEXTJOIN("|",1,G2:G)&"' ",1)

How to group data by age range?

Given data list with two columns: 'Division' and 'Age.'
username year_of_birth
Albert Albo 1977
Bob Bilo 1974
Conan Cornic 1989
Don Duan 1954
Etan Etin 1967
Fabio Forio 1976
I want to put this data into a Pivot Table and group the ages into specified ranges; however, I'm having issues figuring out how to get around grouping them into set increments that don't vary. My first range would need to be 18-24, my next would be 25-29, then 30-34, 35-39, and so on until I hit 64. Then, I would have 65+ all grouped into one, like so:
How could I make it work ?
A simpler (also single formula) might be:
=ArrayFormula(vlookup(year(now())-B2:B+1,Larry,2))
where year of birth is in ColumnB. This though does require a named range (Larry) of:
This repeats the assumption that, wanting month, day, time, everyone is treated as having been born at the very start of the year_of_birth.
A contingency is included for under 18s where 0-17 in the array might be replaced by invalid or such like.
Just for fun, let's see if we can make it in a single formula
Creating a pivot from here is trivial.

Query for SUM values on multiple columns, then substract and compare results

I have the following scenario:
A Google Sheet to collect daily Cash Flow on two shifts (Morning and Afternoon), starting each shift with money on hand (cash) and money on bank account (to pay bills and make transfers as necessary).
The circuit works by recording money IN or money OUT and using the direction of the flow as a basic selector, in order to determine by adding and substracting, how much money came in, and how much came out.
I've been testing with long QUERY formulae to try to come out with results, but so far, I managed to only filter by means of SUM(X). However, I been trying after reading all documentation about Query Formula, to select and sum every income for every shift within the day, do the math, compare with the starting cash, and determine how much money by means of payment, date and shift came in or out.
This is the Query formula for the collected items:
=QUERY(A1:Q,"SELECT A,B, SUM(G), SUM(H), SUM(I), SUM(J), SUM(K) WHERE E='Collected' AND L='Cash' GROUP BY A,B LABEL SUM(G)'Rentals Collected' ",2)
And this is the Query formula for the paid items:
=QUERY(A1:Q,"SELECT A,B, SUM(G), SUM(H), SUM(I), SUM(J), SUM(K) WHERE E='Paid' AND L='Cash' GROUP BY A,B LABEL SUM(G)'Rentals Paid' ",2)
I've also used this Query formula for displaying money available on hand at the start of each shift, for each day.
=QUERY(A:Q, "SELECT A,B,C,D WHERE C IS NOT NULL", 2)
Any ideas?
Here's a Dummy Sheet that recreates the scenario.

Resources