Working with the WHERE clause and SQL operators to refine data requests.
In my last post I covered the basics of the SELECT
statement and what exactly Structured Query Language (SQL) is. In today’s post, we’re adding a new clause to the SELECT
statement that will allow us to constrain our data requests. If this is your first introduction to SQL, I recommend you check out my previous post which you can find here.
The WHERE Clause
Oh WHERE, oh WHERE can my data be? - Eddie Vedder, Pearl Jam lead singer and SQL enthusiast.
Okay so Eddie Vedder probably isn’t an SQL enthusiast, but if he were, I’d bet he would be a big fan of the WHERE
clause.
Put simply, the WHERE
clause is used to filter rows in a table. When we want to limit the number of rows returned based on a condition or set of conditions, we use the WHERE
clause.
Remember our BREWERY
table from last time?
SELECT *
FROM BREWERY;
BREWERY_ID | BREWERY_NAME | BREWERY_STATE | BREWERY_LICENSE |
---|---|---|---|
1000 | Yee-Haw Brewing Co. | TN | HK41/TFA |
1001 | GREEN MAN BREWERY | NC | 3000-TBTL |
1003 | The Black Abbey Brewing Company | TN | DFTBA-10102017 |
1004 | New Belgium Brewing Company | NC | FT/21CRAV |
1005 | Wicked Weed Brewing | NC | WWB-28801 |
1006 | BURIAL BEER CO. | NC | 40-COLAV |
1007 | Bearded Iris Brewing | TN | NASH/615 |
1008 | TWIN LEAF BREWERY | NC | 144/COX |
1009 | CRAFTY BASTARD BREWING | TN | 865-37917 |
1010 | Highland Brewing Company | NC | 28803- HBC |
Let’s say we’re planning a trip to Asheville, NC, a town known for its eccentric style and thriving beer scene. Before we drive up into the mountains to sample some brews, we would like to know what breweries we can potentially visit in NC. Now we could use SELECT * FROM BREWERY
and scroll through our table searching for breweries where the value for the BREWERY_STATE
attribute is TN
or we could use the WHERE
clause.
SELECT *
FROM BREWERY
WHERE BREWERY_STATE = 'TN';
BREWERY_ID | BREWERY_NAME | BREWERY_STATE | BREWERY_LICENSE |
---|---|---|---|
1001 | GREEN MAN BREWERY | NC | 3000-TBTL |
1004 | New Belgium Brewing Company | NC | FT/21CRAV |
1005 | Wicked Weed Brewing | NC | WWB-28801 |
1006 | BURIAL BEER CO. | NC | 40-COLAV |
1008 | TWIN LEAF BREWERY | NC | 144/COX |
1010 | Highland Brewing Company | NC | 28803- HBC |
Maybe instead of looking at a list of all of the breweries in NC, we want to look up a specific brewery we heard about to check and see if it’s located in NC.
Note that the state abbreviation is in single quotation marks signifying that ‘TN’ is a string data type.
SELECT *
FROM BREWERY
WHERE BREWERY_NAME = 'GREEN MAN BREWERY';
BREWERY_ID | BREWERY_NAME | BREWERY_STATE | BREWERY_LICENSE |
---|---|---|---|
1001 | GREEN MAN BREWERY | NC | 3000-TBTL |
Be sure to pay special attention to the case of your string conditions inside your WHERE
clause. Had we tried to use WHERE BREWERY_NAME = 'Green Man Brewery';
our return would have been empty because in the BREWERY
table, “GREEN MAN BREWERY” is in all caps.
SELECT BREWERY_ID, BREWERY_NAME, BREWERY_STATE, BREWERY_LICENSE
FROM BREWERY
WHERE LOWER(BREWERY_NAME) = 'green man brewery';
BREWERY_ID | BREWERY_NAME | BREWERY_STATE | BREWERY_LICENSE |
---|---|---|---|
1001 | GREEN MAN BREWERY | NC | 3000-TBTL |
Because we only included the text manipulation function LOWER
in the where clause and not in the SELECT
clause, the “GREEN MAN BREWERY” was returned in its default case instead of lower case.
If we have any uncertainty surrounding case when searching inside a particular table, most DBMS have text manipulation functions such as UPPER
and LOWER
that we can use to temporarily convert text to one case or another.
The WHERE clause can also be used with UPDATE, INSERT, and DELETE commands, but more on this later.
Conditional Operators
Sometimes we don’t have an exact value we’re looking for. In those search cases we need to use conditional operators. They allow us to expand our search criteria beyond exact values.
Here are some of the most common conditional operators you’ll encounter.
Operator | Description |
---|---|
= | Equality |
> | Greater than |
< | Less than |
>= | Greater than or equal to |
<= | Less than or equal to |
<> | Not equal |
!<> | Not equal |
BETWEEN | Between two values |
IS NULL | Contains a NULL value |
NULL stands for no value. They are empty fields. Empty here means no spaces, no placeholder values like -9999 - nothing. NULL values typically occur in our data when we don’t know the actual value of a field (cell) within our data table so we leave it blank.
If we wanted to find brewery IDs where the BREWERY_ID is between 1002 and 1005, we would write our query like this:
SELECT BREWERY_ID
FROM BREWERY
WHERE BREWERY_ID BETWEEN 1002 AND 1005;
BREWERY_ID | BREWERY_NAME | BREWERY_STATE | BREWERY_LICENSE |
---|---|---|---|
1003 | The Black Abbey Brewing Company | TN | DFTBA-10102017 |
1004 | New Belgium Brewing Company | NC | FT/21CRAV |
1005 | Wicked Weed Brewing | NC | WWB-28801 |
The WHERE
clause in this example actually uses two operators. The AND
in this statement is actually an operator itself.
Logical Operators
Logic Operator | Description |
---|---|
AND | Return only rows that meet all conditions |
OR | Return rows that meet either condition |
NOT | Return only rows that do not meet the specified condition |
Logic operators allow you to combine more than one search condition at a time. For instance if we want to limit our results for breweries where the BREWERY_ID
is 1005 and the state is NC, our query would use the AND
logic operator. If we wanted to return a list of breweries located in NC or TN we would use the OR
operator. The nice thing about logic operators in SQL is that they’re pretty intuitive.
For practice let’s write a query with multiple conditions. Let’s say we want to look at breweries in either NC
or TN
where the BREWERY_ID
is greater than 1005
.
SELECT *
FROM BREWERY
WHERE BREWERY_STATE = 'NC' OR BREWERY_STATE = 'TN' AND BREWERY_ID > 1005;
BREWERY_ID | BREWERY_NAME | BREWERY_STATE | BREWERY_LICENSE |
---|---|---|---|
1001 | GREEN MAN BREWERY | NC | 3000-TBTL |
1004 | New Belgium Brewing Company | NC | FT/21CRAV |
1005 | Wicked Weed Brewing | NC | WWB-28801 |
1006 | BURIAL BEER CO. | NC | 40-COLAV |
1007 | Bearded Iris Brewing | TN | NASH/615 |
1008 | TWIN LEAF BREWERY | NC | 144/COX |
1009 | CRAFTY BASTARD BREWING | TN | 865-37917 |
1010 | Highland Brewing Company | NC | 28803- HBC |
Hmm…
Was this the table you were expecting?
Looks like we’ve got NC breweries where the IDs is below 1005 even though we requested only IDs above 1005. Let’s look closely at what’s actually going on here.
The order in which the operators are evaluated is causing us trouble. In most DBMS environments, the AND
operator is executed first. This means that in our example above, any breweries located in TN and with a BREWERY_ID > 1005 are returned, and any breweries located in NC regardless of their ID.
To fix this problem we just need to be more specific. By adding parentheses around our conditions, we can control the order in which they’re evaluated. Think of your old TI-83 calculator days.
SELECT *
FROM BREWERY
WHERE (BREWERY_STATE = 'NC' OR BREWERY_STATE = 'TN') AND BREWERY_ID > 1005;
BREWERY_ID | BREWERY_NAME | BREWERY_STATE | BREWERY_LICENSE |
---|---|---|---|
1005 | Wicked Weed Brewing | NC | WWB-28801 |
1006 | BURIAL BEER CO. | NC | 40-COLAV |
1007 | Bearded Iris Brewing | TN | NASH/615 |
1008 | TWIN LEAF BREWERY | NC | 144/COX |
1009 | CRAFTY BASTARD BREWING | TN | 865-37917 |
1010 | Highland Brewing Company | NC | 28803- HBC |
To Sum It Up
The WHERE
clause should be used whenever you need to constrain your data. Conditional operators can help you further refine your queries beyond exact matches, and if you find you need multiple conditions, include logic operators such as AND
and OR
.
In the next post of the SQL BASICS series, we’ll continue expanding our SQL toolkit. I’ll go into how grouping rows using the GROUP BY
clause can be handy and how to sort our returned rows using the ORDER BY
clause.