QUERY runs a small SQL-like language over a range. The syntax is real and strict, which is why a formula that looks correct still returns an error.
=QUERY(A1:F500, "select A, sum(D) where C = 'Paid' group by A order by sum(D) desc", 1)Here are the three failures that send people looking for help, and what actually fixes each one.
Problem 1: Column Letters vs Col1
When your range is a normal sheet range, you use letters like A and D. When the range 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.
Problem 2: Quotes Inside Quotes
The query string is wrapped in double quotes, so text values inside it need single quotes. A cell reference has to be concatenated in, not typed in.
=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.
Problem 3: Mixed Data Types Silently Vanish
This is the one that costs people hours. QUERY assigns a single data type per column based on the majority of 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 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.
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.