Unable to figure out datetime query in Google Sheet - google-sheets

Hi Im unable to figure out whats wrong with my datetime query =QUERY(A:G,"SELECT * WHERE G < datetime '2022-08-24 08:45:00'",1) in my Google Sheet it should return 2 rows on the left whos datetimes in G are < 2022-08-24 08:45:00 (also supplied screenshot)

should be:
=QUERY(A:G, "WHERE G < datetime '2022-08-24 08:45:00'", 1)
yyyy-mm-dd hh:mm:ss is the correct format - https://developers.google.com/chart/interactive/docs/querylanguage#literals
and G2 cant be a text string so multiply it by 1:
=(TEXT(DATE(LEFT(B2,4),MID(B2,5,2),
RIGHT(B2,2)),"yyyy-MM-dd")&" "&TEXT(TIME(C2,D2,0),"HH:mm:ss"))*1
but it's better if you use arrayformula:
=ARRAYFORMULA(IFERROR(DATE(LEFT(B2:B, 4), MID(B2:B, 5, 2),
RIGHT(B2:B, 2))+(TIME(C2:C, D2:D, ))))

I have made changes to formula to your G column =DATE(LEFT(B2,4),MID(B2,5,2),RIGHT(B2,2))+(TIME(C2,D2,0)) to make it pure datetime value. Then use below query formula.
=QUERY(A:G,"SELECT * WHERE G < datetime '2022-08-24 08:45:00'",1)
See your google sheet harun24hr.

Suggestion:
Since the QUERY() function runs a Google Visualization API Query Language query across data it runs slower than the usual formulas in google sheets. This will be very noticeable if you have large data. So another way is using
the FILTER() function to filter only the date less than '2022-08-24 08:45:00'. This runs much faster, almost instantly. The only key difference here is you have to manually copy the headers and start on row 2.
You first have to convert your Column G to an actual Date & Time Format using:
=ARRAYFORMULA(IF(B2:B="", "", DATE(LEFT(B2:B,4),MID(B2:B,5,2),RIGHT(B2:B,2))+(TIME(C2:C,D2:D,0))))
Then using Filter:
=FILTER(A1:G, G1:G < DATE(2022,8,24)+time(8,45,0))
Result:
Headers manually copied.
**Just added some test data to see that the filter works.
References:
QUERY
DATE
TIME
FILTER

Related

Google Sheet - Dealing with unusual date format with MAXIFS function

I'm trying to filter data based on email address matching and date matching.
My issue is the dates come in an unusual format (e.g: 2023-01-10 01:21:45 UTC).
I've been using a helper column instead to make the formula lighter. However, for automation purposes it would be much easier to have the true date format integrated to the formula.
Below is the formula I'm currently using in A2. My goal is to remove column D from formula and use only column C instead. I was trying to replace 'Sample Data for LOOKUP'!D:D by =ARRAYFORMULA(DATEVALUE(left(C2:C14,10))) but it does not work.
=filter('Sample Data for LOOKUP'!E:E,'Sample Data for LOOKUP'!D:D=MAXIFS('Sample Data for LOOKUP'!D:D,'Sample Data for LOOKUP'!B:B,"<>",ARRAYFORMULA(REGEXREPLACE('Sample Data for LOOKUP'!A:A,"(.+#)",)),REGEXREPLACE(B2,"(.+#)",)),(REGEXREPLACE(B2,"(.+#)",)=ARRAYFORMULA(REGEXREPLACE('Sample Data for LOOKUP'!A:A,"(.+#)",))),('Sample Data for LOOKUP'!B:B<>""))
Here is a sample file to make it easier to understand my issue:
https://docs.google.com/spreadsheets/d/18R-4m682SeHNBgnzJCM1l0Fef13D5vYG3gmeWDveSYQ/edit#gid=1722273432
I'm trying in cell A2 to cut column D in 'Sample Data for LOOKUP' tab. I would like to use column C instead with the unusual date format.
To get the latest Status for each email address domain listed in column B2:B, preferring statuses where column Lookup!B2:B is not blank, use vlookup() and sort(), like this:
=arrayformula(
iferror(
vlookup(
regexextract(B2:B, "#(.+)"),
sort(
{ regexextract(Lookup!A2:A, "#(.+)"), Lookup!E2:E },
sign(len(trim(Lookup!B2:B))), false,
Lookup!C2:C, false
),
2,
false
)
)
)
See your sample spreadsheet.

Google sheets not recognising a date as a date

On this report I am trying to do some date analysis.
In column G I need to pull all the URLs from column A which have a closing date in the next 7 days.
And in column I, I need all the URLs which the closing date is in the past.
The issue is that when I try to reference the Closing dates in column E it does not read and as such work.
Could I get some help on making sheets read Column E properly and also some help on the formulas I need in Column G and I
Thank you
You might want to look at the DATEVALUE function:
=DATEVALUE(D2)
If cell D2 contains a date in the form of text (such as "26 May 2022"), this formula will return the date as a number. (You can then format the cell to display a particular date format if required.)
For URLs which have ended, you can then do:
=F2 < TODAY()
And for URLs ending in the next 7 days you will need something like:
=IF(F2<TODAY(), FALSE, IF(F2 - TODAY() > 7, FALSE, TRUE))

Multiple search criteria in google sheets

I am trying to make an automated attendance sheet
I have 2 google sheets,
the first one is the responses from a google form that has the name of the students and the date they attended, so it will have duplicated name and duplicated dates.
The second sheet have the names of the students on the left and the dates on the top.
I am trying to automate the second sheet to put "P" under the date that the student was present and "A" when his name is not in the first sheet with that date.
Best i could do was adding an extra column with the letter "p" in the first sheet and using dget to search for the name and date and output the "p" from the extra column, which only worked for one of them for some reason.
=DGET('ATTENDANCE DATE !B:D, "AT", {"NAME", "DATE"; $H$4,12})
I tried to use query also but no luck.
=QUERY('ATTENDANCE DATE'!B7:D,"
SELECT D
WHERE B MATCHES'"&$H9&"' AND C MATCHES '"&I$2&"'
")
Sorry if my question was confusing.
A good solution is to use 4 formulas to do exactly what you like. Each formula has a function:
B1 formula: generates the headers for all the dates with data.
B2 formula: generates the sub-header with the day of the week for each date.
A3 formula: gets all the names.
B3 formula: gets the attendance values for all users. This is the most complexs one.
Here is how it looks:
A
B
1
< fromula 1 >
2
name
< formula 2 >
3
< formula 3 >
< formula 4 >
Before starting there a few things to note
Questions and more information
Please, if at any point you don't understand something, let me know (I'd like this to be a nice resource on how to do formulas).
Also, at the end I left links to all the formulas I use, so you can see what they exactly do.
Locale
I'm using the English locale. this means that I'm using commas , to separate arguments (instead of ;) and array literals (instead of \). if you have function formatting errors, look into it, as this could be the issue.
Sheet names
I've changed the Sheet's names as they are very long and made the formulas harder to follow. Fell free to replace the names on the formulas back to the original name. Here is how I named them:
ATTENDANCE RESPONSES FROM GOOGLE FORM ⟶ Att
LATE/ABSENT RESPONSES FROM GOOGLE FORM ⟶ Late
Formula format
Almost all formulas require "ARRAYFORMULA" to show their full effects. I won't be adding it everywhere as it could get confusing. If you'd like to see what a formula part (doesn't have an equal sign =) does, go to a sheet and do:
=arrayformula(
<paste formula part>
)
Also, parts that are in <some name> are not literal, and represent the code named in between the brackets.
Formula 1
It can be split into 2 formulas:
Get the ordered unique dates
Add a Reason column for each date
Get the dates
The first thing you can use is UNIQUE to get only the unique ones and SORT to sort them. You also need to get them from both sheets as there could be a day that everyone is absent or another where everyone came. SORT(UNIQUE({Att!B2:B; Late!B2:B})) does most of the trick but you also get empty cells. because of that we add a filter. So together:
SORT(UNIQUE(FILTER({Att!B2:B; Late!B2:B}, {Att!B2:B; Late!B2:B}<>"")))
Adding Reason
The problem of it is that the number of column is not fixed (it grows over time). A good workaround is to concatenate the date with a separator and Reason and then split it again. This only works for columns and generates a 2 column, result. Then it can be moved into a single column by using FLATTEN.
FLATTEN(SPLIT(
<previous part>&"␟Reason",
"␟"
))
I'm using ␟ (Symbol For Unit Separator) as the separator as it indicates exactly what it is and is very-very unlikely to be included in the sheet.
If you use that you'll see that the date is shown in numbers. To Change that we'll format the date before concatenating and splitting:
FLATTEN(SPLIT(
TEXT(
<previous part>,
"dd/mmm/yyyy"
)&"␟Reason",
"␟"
))
Now we need to make it a row instead of a column. There is a function that does that: TRANSPOSE.
Complete formula 1
=ARRAYFORMULA(
TRANSPOSE(FLATTEN(SPLIT(
TEXT(
SORT(UNIQUE(FILTER({Att!B2:B; Late!B2:B}, {Att!B2:B; Late!B2:B}<>""))),
"dd/mmm/yyyy"
)&"␟Reason",
"␟"
)))
)
Formula 2
To add the day of the week we need to format the date with TEST and the format ddd, which is the short-version of the name of the day of the week (Mon, Tue, etc).
TEXT(B1:1, "ddd")
Note though that if the value formatted is already text, it will pass it. Because of that, we need to only do this for the columns with dates. One way that I found is to get the even-numbered columns. TO do that, it's a combination of COLUMN (get the number of the column), MOD (get the module), and IF:
IF(MOD(COLUMN(B1:1),2)=0, <formatted text>, "")
This does what we want but we now get "Sun" on columns that there is nothing. The reason is that empty cells are being interpreted as zeros. Because of that we need to add another condition: the cell is not empty.
IF((MOD(COLUMN(B1:1),2)=0)*(B1:1<>""), <formatted text>, "")
To do the logical and I'm using the product because the formula AND would return a single value ("eats" the passed array).
Complete
=ARRAYFORMULA(
IF(
(MOD(COLUMN(B1:1),2)=0)*(B1:1<>""),
TEXT(B1:1, "dddd"),
""
)
)
Formula 3
The third formula is the simplest and should be self-explanatory:
=ARRAYFORMULA(
SORT(UNIQUE(Att!A2:A))
)
Formula 4
This is the final formula. This formula is based on using VLOOKUP to know the value for each person and date.
Making a table to VLOOKUP into
The way of doing that is to generate a key by joining both values into a single text value and set the other values on the other columns. To prevent problems we add a separator to make sure that there are no combination that will be equal. Here is how the table to lookup into looks like:
< name >␟< date >
< status >
< reason >
< name >␟< date >
< status >
< reason >
< name >␟< date >
< status >
< reason >
⋮
⋮
⋮
The key for the first sheet is:
Att!$A$2:$A&"␟"&Att!$B$2:$B
To add the other 2 columns (Present and an empty one) we use a similar trick to Formula 1: we add a separator to split it later on. Because we already are using ␟ for the key, we need another one. In the same block there is another meant for this cases: ␞ (Symbol For Record Separator).
Att!$A$2:$A&"␟"&Att!$B$2:$B&"␞"&"Present"&"␞"&""
or joining the literal text:
Att!$A$2:$A&"␟"&Att!$B$2:$B&"␞Present␞"
This need to be filtered, as there are empty values, which we don't want. We'll use FILTER to do exactly that:
FILTER(Att!$A$2:$A&"␟"&Att!$B$2:$B&"␞Present␞", Att!$A$2:$A<>"", Att!$B$2:$B<>"")
For the second sheet, we do something similar but including the other columns:
FILTER(Late!$A$2:$A&"␟"&Late!$B$2:$B&"␞"&Late!$C$2:$C&"␞"&Late!$D$2:$D, Late!$A$2:$A<>"", Late!$B$2:$B<>"", Late!$C$2:$C<>"")
Note that I've added more conditionals.
This needs to be vertically joined. This can be done with an array literal:
{
<Attr formula>;
<Late formula>
}
Then we need to split the rows to expand into the multiple columns:
SPLIT(
{
FILTER(Att!$A$2:$A&"␟"&Att!$B$2:$B&"␞Present␞", Att!$A$2:$A<>"", Att!$B$2:$B<>"");
FILTER(Late!$A$2:$A&"␟"&Late!$B$2:$B&"␞"&Late!$C$2:$C&"␞"&Late!$D$2:$D, Late!$A$2:$A<>"", Late!$B$2:$B<>"", Late!$C$2:$C<>"")
},
"␞"
)
Using VLOOKUP
Now that we have where to lookup into, we can do it like so:
VLOOKUP(
A3:A&"␟"&C1:1,
<lookup table>,
2,
false
)
Note that the key that we are looking up is the one we generate. Also, this will get the values only below the dates (will fail otherwise).
Adding the reason
Since we know that the cells which are for the reason fail (since <name>␟Reason shouldn't exist), we can use IFERROR to detect it:
IFERROR(
<vlookup status>,
<vlookup reason>
)
The formula for reason is almost identical to the one for status. The only changes are that we lookup into the third column (instead of the second) and we look one to the left:
VLOOKUP(
A3:A&"␟"&OFFSET(C1:1, 0, -1),
<lookup table>,
3,
false
),
Using OFFSET instead of a range ensures that they have the same size.
Final error management
This formula fails when the key doesn't have name or date (which is outside the table or there that entry missing). For that case we add another IFERROR:
IFERROR(
<formula>,
""
)
Complete formula
=ARRAYFORMULA(
IFERROR(
IFERROR(
VLOOKUP(
A3:A&"␟"&C1:1,
SPLIT(
{
FILTER(Att!$A$2:$A&"␟"&Att!$B$2:$B&"␞Present␞", Att!$A$2:$A<>"", Att!$B$2:$B<>"");
FILTER(Late!$A$2:$A&"␟"&Late!$B$2:$B&"␞"&Late!$C$2:$C&"␞"&Late!$D$2:$D, Late!$A$2:$A<>"", Late!$B$2:$B<>"", Late!$C$2:$C<>"")
},
"␞"
),
2,
false
),
VLOOKUP(
A3:A&"␟"&OFFSET(C1:1, 0, -1),
SPLIT(
{
FILTER(Att!$A$2:$A&"␟"&Att!$B$2:$B&"␞Present␞", Att!$A$2:$A<>"", Att!$B$2:$B<>"");
FILTER(Late!$A$2:$A&"␟"&Late!$B$2:$B&"␞"&Late!$C$2:$C&"␞"&Late!$D$2:$D, Late!$A$2:$A<>"", Late!$B$2:$B<>"", Late!$C$2:$C<>"")
},
"␞"
),
3,
false
)
),
""
)
)
Final touches
The final result is something like this.
After that you can simply add formats to your taste. You can also add conditionals ones to more easily see the result.
References
MOD (Google Editors Help)
SPLIT (Google Editors Help)
TEXT (Google Editors Help)
IF (Google Editors Help)
IFERROR (Google Editors Help)
FILTER (Google Editors Help)
UNIQUE (Google Editors Help)
SORT (Google Editors Help)
TRANSPOSE (Google Editors Help)
FLATTEN (Google Editors Help)
ARRAYFORMULA (Google Editors Help)
VLOOKUP (Google Editors Help)
OFFSET (Google Editors Help)
I've completed a not-so-neat solution for you, starting on Row10 in the 'AUTO ATTENDANCE' sheet. It's divided into 4 parts:
The formula in cell D10 auto-populates Row10 with dates and empty cells in between:
=SPLIT(JOIN("|REASON|",SORT(UNIQUE({'ATTENDANCE RESPONSES FROM GOOGLE FORM'!$B$2:$B;'LATE/ABSENT RESPONSES FROM GOOGLE FORM'!$B$2:$B}))),"|")
Row 11 gets the day of the week from row 10 (if the cell above it contains a date:
=IF(ISDATE(D10),TEXT(D10,"dddd"),)
Cell C12 gets all unique names from both response sheets (auto-populates the name column):
=SORT(UNIQUE({'ATTENDANCE RESPONSES FROM GOOGLE FORM'!$A$2:$A;'LATE/ABSENT RESPONSES FROM GOOGLE FORM'!$A$11:$A}))
Cell D12 onwards gets the form responses and does the auto-attendance:
=IF($C12<>"", IF(ISDATE(D$1), IF(IFERROR(QUERY('ATTENDANCE RESPONSES FROM GOOGLE FORM'!$A$2:$B,"select A where A = '"&$C12&"' AND B = datetime '"&TEXT(D$1, "yyyy-mm-dd hh:mm:ss")&"'"), "noresult")=$C12, "PRESENT", IFERROR(QUERY('LATE/ABSENT RESPONSES FROM GOOGLE FORM'!$A$2:$D, "select C where A = '"&$C12&"' and B = datetime '"&TEXT(D$1, "yyyy-mm-d hh:mm:ss")&"'"), "NO RESPONSE")), IFERROR(QUERY('LATE/ABSENT RESPONSES FROM GOOGLE FORM'!$A$2:$D, "select D where A = '"&$C12&"' and B = datetime '"&TEXT(C$1, "yyyy-mm-d hh:mm:ss")&"'"), )), )
The cells with yellow background contain formulae, the ones with green background do not contain formulae but will be auto-populated as the forms get more responses. The single cell with red background (C11), you'll have to write manually ;) Hope this solves your issue!

Google Sheets Query: Bring data by date in cell

I am trying to query a google sheet by date. I have done some research and learned I need to convert to TEXT format so that I can run the comparison, but I am not able to get the syntax correctly:
=query('SheetName'!$A2:$S, "select A Where O=date'"&TEXT(B2,"yyyy-mm-dd")&)
Could you give me some guidance?
Some more info: in my query, B2 is a valid date in date format. Column O has some cells that are text strings and others that are valid dates; I have set the format of the entire column to "Date".
Here is a link to a simple example, feel free to play around with the query: https://docs.google.com/spreadsheets/d/1O4ms9ufvZ_CRLl_LG45hksjRoOJtv0XexbfjCLqFW4I/edit?usp=sharing
See if this works?
=filter('SheetName'!A3:A, 'SheetName'!O3:O=B2)
correct syntax should be:
=ARRAYFORMULA(QUERY(TO_TEXT(SheetName!$A2:$S),
"select Col16 where Col15 = '"&TO_TEXT(DATEVALUE(B2))&"'"))

Select max() in Google Sheet Query on Dates gives different result to =max() formula

I'm trying to return the last time log from a list in Google spreadsheet using Google Sheet query max() function.
=query(A:A, "select max(A)",1)
The time log data (column A) is in text format dd/mm/yyyy hh:mm:ss, which is imported to google sheet using importdata function.
The above query is not returning the correct result. I think it's because the source of data is in text format.
e.g. The above query will return 9/9/2017 23:58:00 while the normal =max(A:A) function returns 12/9/2017 19:12:00.
Is it possible to reformat the text to datetime format within the query clause?
The data sample is from here:
https://docs.google.com/spreadsheets/d/1EwT5ZvCCLLorWomaeJFMhAziWnhW9zTwco9dfwoXJJ4/edit#gid=0
It's possible, for example:
=query(ArrayFormula(1*filter(A:A,NOT(ISBLANK(A:A)))), "select max(Col1)",0)
(and probably something a bit simpler!) but the obvious preferred option is to treat date/times as date/times, not text.

Resources