Multiple CONTAINS in WHERE Clause in Google Sheets Query

This tutorial explains how to specify multiple CONTAINS for partial matching strings in the WHERE clause in Google Sheets Query.

Besides aggregation, the QUERY function in Google Sheets showcases excellent capabilities for string matching. This feature significantly enhances the tool’s ability to perform advanced data filtering.

There are simple comparison operators and five complex string comparison operators to achieve that. The complex string comparison operators are CONTAINS, MATCHES, LIKE, STARTS WITH, and ENDS WITH.

Some of you may already be well aware of the use of CONTAINS and its counterpart, NOT CONTAINS, in Query. Here is an example:

Example 1 (Formula in cell D1): Extract all the ‘Product Codes’ that contain the string ‘ABC’.

=QUERY(A1:A, "SELECT * WHERE A CONTAINS 'ABC' ", 1) // case-sensitive
=QUERY(A1:A, "SELECT * WHERE LOWER(A) CONTAINS 'abc' ", 1) // case-insensitive
Query String Matching with CONTAINS and NOT CONTAINS

Example 2 (Formula in cell E1): Extract all the ‘Product Codes’ that do not contain ‘ABC’.

=QUERY(A1:A, "SELECT * WHERE NOT A CONTAINS 'ABC' ",1) // case-sensitive
=QUERY(A1:A, "SELECT * WHERE NOT LOWER(A) CONTAINS 'abc' ", 1) // case-insensitive

The purpose of using multiple CONTAINS in the Query WHERE clause is to perform multiple substring matches. Let me address that issue, which is the main topic of this post.

Note: You can enter the string to match in a cell, for example, in cell F2, and refer to that cell as follows: '"&F2&"'. This means you should replace 'ABC' (or 'abc') with '"&F2&"' in the above formulas.

Multiple CONTAINS in the QUERY Function and Practicality Issues

Of course, we can use multiple CONTAINS in the QUERY function WHERE clause for multiple substring matches. First, let’s see how to do that.

We can use the following QUERY formula to filter column A where the rows partially match ‘ABC’ or ‘XYZ’ (case-sensitive):

=QUERY(A1:A, "SELECT * WHERE A CONTAINS 'ABC' or A CONTAINS 'XYZ'", 1)

This works wonderfully. However, the issue arises when the number of strings to match increases, requiring many ‘CONTAINS’ and OR logical operators to separate each CONTAINS. This makes the formula longer and more difficult to manage.

So, how do we properly use multiple CONTAINS in the QUERY function WHERE clause?

Let’s find out.

MATCHES: The Alternative to Multiple CONTAINS in Query

Before we proceed with multiple substring matches, let’s replace our D1 and E1 formulas first. We will replace CONTAINS in those formulas with MATCHES.

MATCHES in WHERE Clause (Example Formula in cell D1):

=QUERY(A1:A, "SELECT * WHERE A MATCHES '.*ABC.*' ",1)

NOT MATCHES in WHERE Clause (Example Formula in cell E1):

=QUERY(A1:A,"SELECT * WHERE NOT A MATCHES '.*ABC.*' ",1)

When replacing CONTAINS with MATCHES, ensure to include .* around the criterion. If you want to refer to a cell, for example, cell F2, where you have entered ABC, replace '.*ABC.*' with '.*"&F2&".*'.

Examples of Multiple Partial Matches of Strings

In the earlier examples, I extracted the ‘Product Codes’ that contain/don’t contain the substring ‘ABC’. Now I am going to demonstrate multiple substring matches/mismatches in Query formulas.

See the following formulas:

Formula in D1:

=QUERY(A1:A,"SELECT * WHERE A MATCHES '.*ABC.*|.*DJ.*' ", 1)

Formula in E1:

=QUERY(A1:A, "SELECT * WHERE NOT A MATCHES '.*ABC.*|.*DJ.*' ", 1)
Example of Multiple CONTAINS in WHERE Clause in Query

When replacing a single criterion CONTAINS with multiple criteria MATCHES, in addition to the .* around the criterion, include a | separator between the strings. This allows us to include several partial matching as well as non-matching criteria in a single Query.

Yes! MATCHES-based string matching is my answer to how to use multiple CONTAINS in the WHERE clause in Google Sheets Query.

Specifying a Criteria Range in MATCHES in Query

Assume the conditions (substrings) to match are entered in B2:B3, where ABC is in B2 and DJ is in B3. Then you can replace '.*ABC.*|.*DJ.*' (regular expression) in the formula with the following code:

ArrayFormula("'"&TEXTJOIN(".*|", TRUE, ".*"&TOCOL(B2:B3, 1))&".*'")

Just replacing that regular expression won’t suffice. Use the formula as follows:

=QUERY(A1:A,"SELECT * WHERE A MATCHES "&ArrayFormula("'"&TEXTJOIN(".*|", TRUE, ".*"&TOCOL(B2:B3, 1))&".*'")&" ", 1)

In the above code, the TOCOL function ensures that blank cells, if any, in the criteria range are removed, and the TEXTJOIN function joins the values placing a .*| delimiter in between.

This is the dynamic way to use multiple CONTAINS in the WHERE clause in Google Sheets Query using MATCHES substring match.

Before concluding, here’s one bonus tip. Do you know how to use CONTAINS and NOT CONTAINS in a single Query?

CONTAINS and NOT CONTAINS in a Single Query Formula

Here, for two criteria partial match, one containing and the other not containing, you can use CONTAINS in the WHERE clause. For single as well as multiple conditions (matches/mismatches), use MATCHES.

Single Condition CONTAINS and NOT CONTAINS:

=QUERY(A1:A, "SELECT * WHERE A CONTAINS 'ABC' AND NOT A CONTAINS 101", 1)

Multiple MATCHES and NOT MATCHES (Multiple CONTAINS and NOT CONTAINS):

=QUERY(A1:A, "SELECT * WHERE A MATCHES '.*AB.*|.*DJ.*' AND NOT A MATCHES '.*101.*|.*102.*' ", 1)

Resources

Prashanth KV
Prashanth KV
Your Trusted Google Sheets and Excel Guide Prashanth KV brings a wealth of experience in Google Sheets and Excel, cultivated through years of work with multinational corporations in Mumbai and Dubai. As a recognized Google Product Expert in Docs Editors, Prashanth shares his expertise through insightful blogging since 2012. Explore his blog for practical tips and guidance on maximizing your spreadsheet skills.

3-D Referencing Structured Data Tables in Google Sheets

When you have several tables within a single sheet—not across multiple sheets in a...

Fill Empty Cells with the Value from Above in Excel

There are two main approaches to fill empty cells with the value from above...

Excel: Jump to the VLOOKUP Result Cell

In Excel, we can create a hyperlink to jump to the VLOOKUP result cell...

How to Jump to the Current Date Cell in Excel

We can create a hyperlink to quickly jump to the first occurrence of the...

More like this

3-D Referencing Structured Data Tables in Google Sheets

When you have several tables within a single sheet—not across multiple sheets in a...

Case-Sensitive Running Count in Google Sheets

This tutorial provides a solution for incorporating case sensitivity into the running count of...

Fix Fractional Percentage Formatting Issues in Google Sheets

Applying data validation is the only effective solution to resolve issues related to fractional...

11 COMMENTS

  1. I am hoping you can help. I am trying to populate data based on two separate requests. Column E has school grades (EE3, EE4, Kindergarten, 1st grade, etc.), and Column H has testing requested (speech, cognition, dyslexia, etc.). I need two kinds of data to populate into one spreadsheet:

    1. If the school grade is not EE3 or EE4, no matter the testing requested.
    2. If the school grade is EE3 or EE4 and they are only requesting speech.

    I can get the first populated, but I cannot seem to figure out how to add the second request of “if/then” to the same spreadsheet.

    • Hi Ashley Morland,

      You can try the following QUERY formula:

      =QUERY({'Sample Sheet'!E:H},"Select * where (Col1 matches 'EE3|EE4' and Col4='speech') or
      (not(Col1) matches 'EE3|EE4' and Col1 is not null)")

      You need to make two changes in this formula:

      1. Replace Sample Sheet with the actual sheet name containing the source data.
      2. Replace commas with semicolons as per your LOCALE settings.

  2. Hello! This solution helped me in my report.

    The only thing I can’t figure out with the formula is instead of B2:B3, how to use a larger range, for example, B2:B20, and it has only five values.

    How do you factor in the blank cells?

    Looking forward to your answer.

  3. The array formula you used to match conditions as a range is genius. Thank you so much for sharing. I haven’t seen this solution anywhere else.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.