AI Content Creation

Google Sheets QUERY Function Help

QUERY is the most powerful function in Sheets and the least forgiving. This guide covers the syntax, the failures that send people looking for help, and what actually fixes each one.

By FITS TeamAugust 2, 20268 min read

How to Use the QUERY Function in Google Sheets

You use QUERY by giving it a range and a query string. The formula below pulls two columns and keeps only the paid rows.

=QUERY(A1:F500, "select A, D where C = 'Paid'", 1)

The three arguments do three jobs. The first is the data. The second is a small SQL-like language. The third is the number of header rows, and 1 is the safe choice when row 1 holds column names.

The query language has ten clauses, and every one of them is optional. They must appear in this order if you use them:

select, where, group by, pivot, order by, limit, offset, label, format, options

There is no from clause, because the range itself is the first argument. An empty query string returns the whole range unchanged. A query that omits select returns every column, which is the same as select *.

How to Filter Rows With a QUERY Where Clause

The where clause filters rows, and the literal syntax is what breaks most formulas. Text values need single quotes, numbers take none, and dates need the date keyword.

=QUERY(A1:F500, "select A, D where C = 'Paid' and D > 100 and B >= date '2026-08-02'", 1)

Conditions combine with and, or, and not. They work as operators between comparisons, not as function calls. Timestamps use datetime '2026-08-02 14:30:00' instead of the date keyword.

One trap worth naming: the date comparison silently fails when the column is text that looks like a date. Convert the column with DATEVALUE outside the query first, then filter it.

How to Fix the QUERY Column Letters vs Col1 Error

Column letters like A and D only work when the first argument is a real range. When the data comes from another function, the letters stop working.

=QUERY(IMPORTRANGE("sheet_id", "Data!A:F"), "select Col1, Col4 where Col3 = 'Paid'", 1)

Anything wrapped in IMPORTRANGE, FILTER, or an array literal needs Col1, Col2, Col3 instead of letters. Mixing the two styles in one query throws an error every time.

The error names the offender. It reads: Unable to parse query string for Function QUERY parameter 2: NO_COLUMN: C. If you see NO_COLUMN, check whether the first argument is a computed range.

How to Fix QUERY Quote Nesting and Cell References

The query string is wrapped in double quotes, so text values inside it need single quotes. A cell value has to be concatenated in rather than typed.

=QUERY(A1:F500, "select A, D where C = '" & H1 & "' and D > " & H2, 1)

Text needs the single quotes around it. Numbers must not have them. Dates need their own wrapper, written as date '2026-08-02' in the query string.

One related misconception: toDate() does not parse text. Its valid inputs are a date, a datetime, or a number of epoch milliseconds, so toDate('2026-08-02') on a text column errors out. Convert text dates with DATEVALUE in a helper column instead.

Why QUERY Returns Blank Cells for Mixed Data Types

This is the one that costs people hours. QUERY assigns a single data type per column based on the majority of its values.

If an ID column is 80 percent numbers and 20 percent text, the text entries are treated as nulls. They do not error. They just come back blank, and nobody notices until the totals are wrong.

The standard fix is to force the whole column to text before querying it.

=QUERY(ARRAYFORMULA(TO_TEXT(A1:F500)), "select Col1, Col4 where Col3 = 'Paid'", 1)

That saves the rows, but now every number is text. Your sum() and order by clauses stop behaving, so you wrap parts of the output in VALUE() and the formula grows again.

The reverse case has its own tool. Numbers stored as text come back with TO_PURE_NUMBER in place of TO_TEXT. The format option no_format does not help here, because it changes display strings only and never touches column types.

How to Sum, Count, and Group Rows With QUERY

QUERY supports exactly five aggregation functions: sum, count, avg, min, and max. Combined with group by, they collapse rows the way a pivot table does.

=QUERY(A1:F500, "select A, sum(D) group by A order by sum(D) desc label sum(D) 'Total'", 1)

The order by clause can repeat the aggregate expression, and label renames the output header. The label is display metadata only, so you cannot reference Total in a where clause. Repeat the expression instead.

There is also no HAVING clause in this query language, so filtering on an aggregate needs a nested QUERY.

=QUERY(QUERY(A1:F500, "select A, sum(D) group by A", 1), "select Col1, Col2 where Col2 > 100", 1)

The inner query produces the totals, and the outer query filters them. Note the outer query uses Col1 and Col2, because its input is a computed range, not a sheet range.

How to Do a Case Insensitive Match in QUERY

Every QUERY text operator is case sensitive. contains, starts with, ends with, like, and matches all treat Bug and bug as different words.

The portable fix wraps both sides in lower().

=QUERY(A1:F500, "select A where lower(C) contains 'paid'", 1)

The matches operator uses Java regular expressions, so the case insensitive flag goes straight into the pattern: where C matches '(?i).*paid.*'. That one avoids touching the column at all.

QUERY Not Working: What Each Error Message Means

QUERY fails in four distinct ways, and the wording tells you which one you have. Read the message before rewriting the formula.

PARSE_ERROR: Unable to parse query string for Function QUERY parameter 2: PARSE_ERROR: Encountered ... This is a syntax fault. Usual causes are a missing quote, a clause out of order, or a spreadsheet function pasted inside the string.

NO_COLUMN: ...parameter 2: NO_COLUMN: C. The query names a column the range does not have. Letters on a computed range are the common case.

Empty output: the cell shows #N/A and the hover text reads Query completed with an empty output. The query is valid and zero rows matched. Check the filter values and the column types before blaming the syntax.

Timeout: very large ranges with group by or pivot can hit the spreadsheet calculation limit and return #ERROR!. Shrink the range or move the aggregation out of QUERY.

How to Set the QUERY Headers Argument

The third argument controls headers: leave it off or -1 and Sheets guesses, 0 means no header rows, and 1 treats the first row as headers.

The guess fails when your data is all text, because nothing marks row 1 as different. Set 0 or 1 explicitly and the behavior stops being a surprise. A third argument of 2 or more concatenates that many top rows into one header, joined with spaces, which is almost never what you want.

One quirk survives even headers set to 0. A query with an aggregation still prints a default header such as sum next to the values. Silence it with an empty label: label sum(D) ''.

The FITS Way (Ask the Question Instead)

Sometimes you do not need a live pivot. You need one answer about the rows in front of you. With FITS, you ask in plain English and skip the query language.

=FITS("Which of these accounts is unpaid and over 30 days old? Return only the account names, comma separated. Data: " & JOIN(" | ", A2:C200))

No Col references. No quote nesting. Mixed data types in a column are read the way a person would read them, so text IDs are not dropped.

It also works row by row, which is where QUERY has no answer at all.

=FITS("Does this support ticket describe a billing problem? Answer Yes or No only: " & B2)

Put that in a helper column and QUERY can filter on it. The two work well together once the judgment call has its own column.

When to Use Each

QUERY is the right tool for live aggregation over structured, clean, single-type columns. Reach for =FITS() when the filter needs judgment, when the source data is mixed and messy, or when you want an answer rather than a table. Related jobs use the same pattern: writing IF THEN logic in plain English, generating the formula you cannot remember, and pulling data from a website without XPath. The full tour is in automating Google Sheets tasks you used to need regex for.

Frequently Asked Questions

How do I use the QUERY function in Google Sheets?

Give QUERY a range and a query string: =QUERY(A1:F500, "select A, D where C = 'Paid'", 1). The first argument is the data. The second is the SQL-like language with ten optional clauses: select, where, group by, pivot, order by, limit, offset, label, format, options. The third is the number of header rows, and 1 is the safe choice when row 1 holds column names.

Why is my QUERY function returning blank cells?

QUERY assigns each column one data type based on the majority of its values. If an ID column holds 80 percent numbers and 20 percent text, the text entries become silent nulls rather than errors. Force the column to one type before querying it with TO_TEXT. The reverse problem, numbers stored as text, is fixed the same way with TO_PURE_NUMBER.

How do I make QUERY case insensitive?

Wrap both sides in lower(): =QUERY(A1:F500, "select A where lower(C) contains 'paid'", 1). The operators contains, starts with, ends with, like, and matches are all case sensitive, so Bug and bug are different words to them. For matches, which uses Java regular expressions, put the flag in the pattern instead: where C matches '(?i).*paid.*'.

Can you use IF inside a QUERY function?

No. Spreadsheet functions like IF, VLOOKUP, and CONCATENATE do not work inside the query string. AND, OR, and NOT do work there, but only as operators between conditions, not as function calls. Do the filtering in the where clause, or compute a helper column with IF outside QUERY and filter on that column.

What does the NO_COLUMN error mean in QUERY?

NO_COLUMN means the query references a column the data range does not have. The full text looks like: Unable to parse query string for Function QUERY parameter 2: NO_COLUMN: C. The usual cause is using column letters when the first argument comes from IMPORTRANGE, FILTER, or an array literal. Computed ranges have no letters, so reference columns as Col1, Col2, Col3.

How do I filter by date in QUERY?

Use the date keyword with an ISO string in quotes: =QUERY(A1:F500, "select A where B >= date '2026-08-02'", 1). For timestamps use datetime 'yyyy-MM-dd HH:mm:ss'. The comparison fails if the column is text that looks like a date, and toDate() does not parse text strings. Convert text dates with DATEVALUE outside the query first.

Skip the Query Language

FITS puts plain-English AI formulas inside Google Sheets. Ask the question the way you would ask a colleague. Free tier included.