Learning SQL: The SELECT Statement and the WHERE Clause
By: Michael Mcmillan
Tags: Sql Tutorial, Database Development, Sql, Sqlite, Database

Photo by Alvaro Reyes on Unsplash

In my last article on learning SQL, I discussed how to query a database table using the SELECT statement. In this article, I’ll discuss how to refine queries by using the WHERE clause.

The SELECT Statement

As a quick review, the SELECT statement is used to retrieve data from a database table (called a query). Here is an example:

sqlite> select first_name, last_name from demographics;

Cynthia|Fehrenbach

Raymond|Williams

Danny|Martin

Jonathan|Childs

Meredith|Stanton

Jessica|Wise

You can also specify all the columns by replacing the column names with an asterisk:

sqlite> select * from demographics;

1234|Cynthia|Fehrenbach|Little Rock|1988-02-09|Graphic Arts

1231|Raymond|Williams|Sheridan|1985-12-07|Classics

2314|Danny|Martin|Greenbrier|1978-06-12|Information Technology

2143|Jonathan|Childs|Hot Springs|1988-05-13|Film and Sound

3124|Meredith|Stanton|Maumelle|1985-06-03|English

2341|Jessica|Wise|North Little Rock|1984-08-01|English

There are many situations, though, where you want to restrict the data returned from a query to a subset of the data stored in the table. The WHERE clause can help you refine your queries to match the restrictions you want.

The WHERE Clause with Relational Operators

The purpose behind the WHERE clause is to request a subset of the data in a table based on a condition or a specification. Let’s start with the syntax template for the WHERE clause:

select [*, columns] from table-name where [condition/specification];

Let’s start with supplying the WHERE clause with a condition. Here’s one example:

sqlite> select * from demographics where last_name = 'Fehrenbach';

1234|Cynthia|Fehrenbach|Little Rock|1988-02-09|Graphic Arts

The condition asks to retrieve only the row where the last name is “Fehrenbach”.

Here is another example:

sqlite> select * from demographics where major = "English";

3124|Meredith|Stanton|Maumelle|1985-06-03|English

2341|Jessica|Wise|North Little Rock|1984-08-01|English

Here the condition asks for only rows where the major field has “English” in it and two rows were returned.

The last two examples used an equality condition but you can use other relational operators as well. Here is an example using the < operator:

sqlite> select first_name, last_name, dob from demographics where dob < '1985';

Danny|Martin|1978-06-12

Jessica|Wise|1984-08-01

Here is an example using the != operator:

sqlite> select first_name, last_name, major from demographics where major != "English";

Cynthia|Fehrenbach|Graphic Arts

Raymond|Williams|Classics

Danny|Martin|Information Technology

Jonathan|Childs|Film and Sound

The WHERE Clause with Boolean Operators

Sometimes just one condition in a WHERE clause is not enough. You can combine two or more conditions using a Boolean operator. The Boolean operators are and, or, and not.

The and operator is used for queries where the rows returned have to match both conditions. Here is a first example where the query searches for a last name that starts with a letter between M and Z and a major that is not English, with the last names placed in alphabetical order:

sqlite> select * from demographics where last_name > 'L' and major != 'English' order by last_name;

2314|Danny|Martin|Greenbrier|1978-06-12|Information Technology

1231|Raymond|Williams|Sheridan|1985-12-07|Classics

Here is another example where the query searches for an English major born on or after 1985:

sqlite> select first_name, last_name, major from demographics where major = 'English' and dob > '1985';

Meredith|Stanton|English

The or operator will return queries that match either of the conditions. Here is an example where the query searches for rows where the student is born before 1988 or their hometown is Little Rock:

sqlite> select last_name, dob, hometown from demographics where dob < '1988' or hometown = "Little Rock";

Fehrenbach|1988-02-09|Little Rock

Williams|1985-12-07|Sheridan

Martin|1978-06-12|Greenbrier

Stanton|1985-06-03|Maumelle

Wise|1984-08-01|North Little Rock

The first row was born in 1988 but her hometown is Little Rock so it matched the query.

The not operator simply negates the condition presented after it. For example, to find all the students who are not English majors, the query can be written like this:

sqlite> select first_name, last_name, major from demographics where not major = "English";

Cynthia|Fehrenbach|Graphic Arts

Raymond|Williams|Classics

Danny|Martin|Information Technology

Jonathan|Childs|Film and Sound

Writing a query like this is not better or worse than using the != operator, but you should always strive for understandability since it is likely other people will be reading your queries or you may need to revisit a query later and one that is written in an unclear way will take you longer to figure out.

Pattern Matching with LIKE

Most of the queries I have performed so far have involved exact values, such as a string data, or a name, or a major. In this section I’m going to introduce how to perform queries that match patterns of data, such as words starting with “M” or words that include “iec” in them.

In order to work with patterns, we have to work wildcard characters that are used to specify patterns. There are two wildcard characters used in SQL: % and _ (underscore). Let’s take some time now to see how these wildcard characters work.

The % wildcard operator is used to match any string of zero or more characters. For example, if you want to query all majors that start with the letter “E”, you can write "E%" and this will match “English” and “Economics”.

You can also use the % operator at the end of a pattern. The pattern “%s” will match any string of one or more characters that has an “s” at the end of the string.

The _ character (underscore) is used to match any one character in a string. For example, the pattern “____” will match any four-character string, and “E___” will match any string that starts with “E” and has three other characters.

With all this in mind, let’s look at some examples. This first example returns all the students whose major starts with an “E”:

sqlite> select last_name, major from demographics where major like "E%";

Stanton|English

Wise|English

Hodges|Economics

This next example matches all students whose birthday was in 1985:

sqlite> select first_name, last_name from demographics where dob like '1985%';

Raymond|Williams

Meredith|Stanton

Range Filtering with BETWEEN

You can use the BETWEEN clause to query a table for a set of values that is between two specified values. The syntax template for BETWEEN is:

select column-names from table-name where column-name BETWEEN value1 and value2

For this section, I have added a grade point average (gpa) column to the table. In a later article I’ll show you how to do this. For now, though, let’s use the gpa column to demonstrate how the BETWEEN clause works.

First, here is a list of all the rows so you can see the added gpa values:

sqlite> select * from demographics;

1234|Cynthia|Fehrenbach|Little Rock|1988-02-09|Graphic Arts|3.64

1231|Raymond|Williams|Sheridan|1985-12-07|Classics|2.43

2314|Danny|Martin|Greenbrier|1978-06-12|Information Technology|3.27

2143|Jonathan|Childs|Hot Springs|1988-05-13|Film and Sound|3.52

3124|Meredith|Stanton|Maumelle|1985-06-03|English|3.72

2341|Jessica|Wise|North Little Rock|1984-08-01|English|3.55

4213|Mindy|Hodges|North Little Rock|1984-12-23|Economics|3.71

Here is a first example where we query the table for gpa values that are between 3.3 and 3.6:

sqlite> select last_name, gpa from demographics where gpa between 3.3 and 3.6;

Childs|3.52

Wise|3.55

You can also use the BETWEEN clause with strings, as in this example:

sqlite> select last_name, major from demographics where major between 'A' and 'F';

Williams|Classics

Stanton|English

Wise|English

Hodges|Economics

You can negate a BETWEEN query by using NOT , like this:

sqlite> select last_name, gpa from demographics where gpa not between 3.3 and 3.6 order by gpa;

Williams|2.43

Martin|3.27

Fehrenbach|3.64

Hodges|3.71

Stanton|3.72

Notice that the gpa values are ordered so that the lower gpa values are shown first.

Keep in mind that the BETWEEN clause is shorthand for using WHERE and AND :

sqlite> select last_name, gpa from demographics where gpa >= 3.3 and gpa <= 3.6 order by gpa;

Childs|3.52

Wise|3.55

List Filtering with IN

Another way to perform a query is to ask that the query return the rows that match one or more values of a given list. This is done using the IN keyword.

Here is the syntax template for IN :

select columns from table where column IN (list-of-values);

Here is an example of using IN to return a list of majors that match a given list:

sqlite> select last_name, major from demographics where major in ('English','Economics');

Stanton|English

Wise|English

Hodges|Economics

Here is another example where the specified list is a list of grade point averages:

sqlite> select last_name, major, gpa from demographics where gpa in (3.70, 3.71, 3.72);

Stanton|English|3.72

Hodges|Economics|3.71

Keep in mind that using the IN keyword is another way of writing a query that uses WHERE with a series of OR s, as in this rewrite from the example of majors above:

sqlite> select last_name, major from demographics where major = 'English' or major = 'Economics';

Stanton|English

Wise|English

Hodges|Economics

That wraps up my discussion of querying using the SELECT statement. In my next article I’ll begin looking at SQL operators and functions.

Thanks for reading and please respond to this article with your comments and suggestions or drop me an email at mmmcmillan1@att.net.