Showing posts with label MySQL. Show all posts
Showing posts with label MySQL. Show all posts

Sunday, August 30, 2026

Module 9 Set Matching with IN and NOT IN

Module 9

Set Matching with IN and NOT IN

A step-by-step, hands-on SQL practice lesson — with a live SQL playground

SELECT student_name, room FROM class_room WHERE room IN ('A101', 'B201');

After learning how to filter rows with WHERE, I can make my queries much cleaner when I need to match a column against several possible values. That is where IN becomes useful. Instead of writing many OR conditions, I can place the allowed values inside one list. In this lesson, I practice both IN and NOT IN with the class_room table, learn the important NULL behavior, and build queries step by step until the pattern feels natural.

Introduction

What You'll Learn — and Why IN Matters

I use IN when a column can match one of several specific values. For example, if I want students in rooms A101, B201, or C301, I do not need to write three separate equality checks. I can use one readable condition:

WHERE room IN ('A101', 'B201', 'C301')

NOT IN reverses the membership test. It lets me find rows whose value is not in the listed set.

๐ŸŽฏ Objective

By the end of this lesson, you will be able to:

  • Explain what a set of matching values means in SQL.
  • Use IN to match a column against several exact values.
  • Use NOT IN to exclude several exact values.
  • Convert long OR conditions into cleaner IN conditions.
  • Use IN with numbers, text values, and other SQL expressions.
  • Combine IN or NOT IN with AND, OR, and other filters.
  • Understand why NULL can make NOT IN behave unexpectedly.
  • Choose between IN, NOT IN, BETWEEN, and comparison operators.

⚠️ What to Avoid

Important set-matching warnings
  • Do not confuse IN with a range. IN (8, 9, 10) means those exact values, not every value between 8 and 10.
  • Do not forget quotes around string values such as 'active' or 'A101'.
  • Be careful with NOT IN when NULL values are possible. SQL's three-valued logic can produce no match for rows involving NULL.
  • Do not put duplicate values in a list just because they are allowed. Duplicates do not add a new match.
  • Do not build an enormous hard-coded list when a lookup table or subquery would be easier to maintain.

๐Ÿ’ก Important to Know

The core idea

column IN (value1, value2, value3) is a compact way of asking whether the column equals any one of the listed values. Conceptually, room IN ('A101','B201') is similar to room = 'A101' OR room = 'B201'.

Requirements

What You'll Need Before Starting

Operating SystemWindows, macOS, Linux, or another operating system that can run MySQL. The SQL concepts in this lesson are portable across these systems.
Database ServerMySQL installed and running. If you need installation help, see How to Install MySQL Step by Step for Beginners.
Optional: XAMPPXAMPP plus phpMyAdmin provides a visual way to run the SQL. See How to Install XAMPP Step by Step for Beginners (Complete Guide 2026).
Prior knowledgeYou should know basic SELECT and WHERE. For a refresher, review Module 1: Mastering the SQL SELECT Statement (A Step-by-Step Guide).

No installation is required for the browser playground below. The real practice steps are written for MySQL or phpMyAdmin.

Practice

Step-by-Step Practice: IN and NOT IN

I recommend following these steps in order. I first prepare the database, then I test exact matching, replace repeated OR conditions with IN, and finally practice NOT IN, NULL handling, and subqueries.

1 Open MySQL or phpMyAdmin

On Windows, macOS, or Linux, open your MySQL client. If you use XAMPP, start MySQL and open phpMyAdmin. In the terminal, I can connect with:

mysql -u root -p

The basic IN syntax is:

SELECT column1, column2
FROM table_name
WHERE column_name IN (value1, value2, value3);

The opposite syntax is:

SELECT column1, column2
FROM table_name
WHERE column_name NOT IN (value1, value2, value3);

2 Create a Database and Verify It

I create a separate practice database so the examples are easy to repeat without changing another project.

CREATE DATABASE module9_in_practice;
SHOW DATABASES;
USE module9_in_practice;

After SHOW DATABASES;, confirm that module9_in_practice appears in the database list.

3 Create the class_room Table

Now I create a small table with repeated categories such as rooms and statuses. These repeated values are ideal for practicing set matching.

CREATE TABLE class_room (
  id INT PRIMARY KEY,
  student_name VARCHAR(80),
  grade_level INT,
  score DECIMAL(5,2),
  status VARCHAR(20),
  room VARCHAR(20)
);

Verify the database table and its columns:

SHOW TABLES;
DESCRIBE class_room;

4 Insert Sample Data

I insert eight students so the same room and status values appear more than once.

INSERT INTO class_room (id, student_name, grade_level, score, status, room) VALUES
(1, 'Dara', 7, 62.50, 'active', 'A101'),
(2, 'Sokha', 8, 74.00, 'inactive', 'A101'),
(3, 'Maly', 8, 81.50, 'active', 'B201'),
(4, 'Vannak', 9, 88.00, 'pending', 'B201'),
(5, 'Lina', 9, 93.50, 'active', 'C301'),
(6, 'Rith', 10, 69.00, 'inactive', 'C301'),
(7, 'Nita', 10, 97.00, 'active', 'D401'),
(8, 'Bora', 11, 55.00, 'pending', 'D401');
SELECT * FROM class_room ORDER BY id;

5 Match Several Text Values with IN

Suppose I want students in rooms A101, B201, and C301. I can write one clean condition:

SELECT student_name, room
FROM class_room
WHERE room IN ('A101', 'B201', 'C301')
ORDER BY room, student_name;

This is equivalent to writing:

SELECT student_name, room
FROM class_room
WHERE room = 'A101'
   OR room = 'B201'
   OR room = 'C301'
ORDER BY room, student_name;
My practice note

When I see several equality checks against the same column, I look for an opportunity to use IN. It usually makes the intention easier to read.

6 Match Several Numeric Values with IN

IN also works with numbers. If I want students in grades 7, 9, or 11, I can write:

SELECT student_name, grade_level
FROM class_room
WHERE grade_level IN (7, 9, 11)
ORDER BY grade_level, student_name;

Notice the difference between a set and a range:

-- Exact set: only 7, 9, or 11
WHERE grade_level IN (7, 9, 11)

-- Continuous range: every value from 7 through 11
WHERE grade_level BETWEEN 7 AND 11;

This distinction is important: IN is about membership in a specific list, while BETWEEN is about a continuous range.

7 Use NOT IN to Exclude a Set

Now I want every student except those in rooms A101 and D401.

SELECT student_name, room
FROM class_room
WHERE room NOT IN ('A101', 'D401')
ORDER BY room, student_name;

Conceptually, this is similar to:

WHERE room <> 'A101'
  AND room <> 'D401'

So NOT IN is especially useful when the list of excluded values grows.

8 Combine IN or NOT IN with Other Conditions

Real SQL queries often combine set matching with another filter. For example, I can find active students in selected rooms:

SELECT student_name, room, status
FROM class_room
WHERE status = 'active'
  AND room IN ('A101', 'B201', 'C301')
ORDER BY room, student_name;

I can also combine a numeric set with a score condition:

SELECT student_name, grade_level, score
FROM class_room
WHERE grade_level IN (8, 9, 10)
  AND score >= 75
ORDER BY grade_level, score DESC;

For more complex logic, parentheses make my intention clearer:

SELECT student_name, room, status
FROM class_room
WHERE (room IN ('A101', 'B201') OR status = 'pending')
  AND grade_level >= 8;

9 Understand NULL with NOT IN

This is one of the most important details I want to remember. SQL does not treat NULL as an ordinary value. A condition involving NULL can evaluate to UNKNOWN, not simply true or false.

For example, if a column can contain NULL, I should not assume that this always returns every row outside the listed values:

WHERE room NOT IN ('A101', 'B201')

If I specifically want rows whose room is either outside the list or NULL, I can say that explicitly:

WHERE room NOT IN ('A101', 'B201')
   OR room IS NULL

For larger projects, NOT EXISTS can also be a safer and clearer option when the exclusion list comes from another table or subquery, especially when NULLs may be present.

Troubleshooting

5 Common Problems and Solutions

Problem 1: I forgot quotes around text values

I wrote WHERE room IN (A101, B201) and MySQL reports an error or interprets the names incorrectly.

SolutionString values should normally be written with quotes: WHERE room IN ('A101', 'B201').

Problem 2: I expected IN to include every number in a range

I wrote grade_level IN (7, 11) and expected grades 7 through 11.

SolutionIN matches only the exact listed values. Use BETWEEN 7 AND 11 for a continuous inclusive range.

Problem 3: NOT IN behaves strangely when NULL exists

I expected NOT IN to return every row that is not one of the listed values, but rows involving NULL do not appear.

SolutionRemember SQL's NULL logic. If NULL should be included, add OR column_name IS NULL. When excluding values from another query, consider NOT EXISTS.

Problem 4: My IN list contains duplicate values

I have IN ('A101', 'A101', 'B201') and wonder whether the duplicate changes the result.

SolutionDuplicates do not create duplicate result rows. Keep the list unique because it is clearer and easier to maintain.

Problem 5: My IN condition is mixed with AND and OR incorrectly

The query returns more rows than I expected after I add several logical conditions.

SolutionUse parentheses to make the intended groups explicit. Test each condition separately, then combine them one at a time.

Conclusion

What I Want You to Remember

The main lesson I take from Module 9 is simple: IN is for matching a value against a specific set, while NOT IN is for excluding that set.

In my own SQL practice, I find IN especially helpful when I see repeated conditions such as room = 'A101' OR room = 'B201' OR room = 'C301'. Replacing them with room IN ('A101', 'B201', 'C301') makes the query easier to scan.

Expected result from this lesson

You should now be able to use IN and NOT IN for exact set matching, combine them with other filters, distinguish them from BETWEEN, and recognize the special care required when NULL values are involved.

Next step: keep practicing SQL filtering by combining the operators you have learned into complete real-world queries.

Homework

Homework & Quiz

๐Ÿ“ Homework Task

Using the class_room table, write these queries yourself before checking the live playground:

  1. Find students whose room is one of A101, B201, or C301.
  2. Find students whose room is not A101 or D401.
  3. Find students whose grade level is exactly 7, 9, or 11.
  4. Find active students whose room is in A101, B201, or C301 and whose score is at least 75.
  5. Create a query that demonstrates how you would include NULL rooms while excluding A101 and B201.

๐Ÿงช Quiz: Test Your Understanding (10 Questions)

Pick one answer per question, then click Submit to see your score instantly.

1. What does room IN ('A101', 'B201') mean?

2. Which syntax correctly matches several status values?

3. What does NOT IN ('A101', 'D401') do?

4. What is the main difference between IN and BETWEEN?

5. Which condition is equivalent to grade_level IN (7, 9, 11)?

6. What should you remember about NULL and NOT IN?

7. Which query finds active students in rooms A101 or B201?

8. Do duplicate values inside an IN list create duplicate result rows?

9. What is a good reason to use IN instead of many OR comparisons?

10. What is the main idea of Module 9?

0 / 10

Try It Live

๐Ÿงช Live SQL Playground

This browser playground uses SQLite through WebAssembly. It is designed to practice the set-matching ideas in this lesson; use your real MySQL server for MySQL-specific testing.

class_roomid INTEGER PK
student_name TEXT
grade_level INTEGER
score REAL
status TEXT
room TEXT
Loading SQL engine…
Run a query to see results here.

FAQ

Frequently Asked Questions

1. What does IN do in SQL?

IN checks whether a column value matches one of the exact values in a specified list.

2. What does NOT IN do?

NOT IN checks for values that are not members of the listed set. NULL requires special consideration.

3. Is IN the same as BETWEEN?

No. IN matches a discrete list of exact values. BETWEEN describes a continuous inclusive range.

4. Can IN be used with numbers?

Yes. For example, grade_level IN (7, 9, 11) matches exactly 7, 9, or 11.

5. Can IN be used with text?

Yes. String values should normally be quoted, such as status IN ('active', 'pending').

6. Is IN better than many OR conditions?

When the same column is compared against several exact values, IN is usually more concise and easier to read. The optimizer can still choose an appropriate execution plan.

7. Why should I be careful with NOT IN and NULL?

SQL uses three-valued logic. Comparisons involving NULL can evaluate to UNKNOWN, so NULL rows may not be returned by NOT IN. Use explicit IS NULL handling when needed.

8. Can I combine IN with AND and OR?

Yes. You can combine set matching with other conditions. Use parentheses when several AND/OR conditions could be interpreted in different ways.

9. Can IN use a subquery?

Yes. A common pattern is WHERE department_id IN (SELECT id FROM departments ...). For exclusions with possible NULLs, NOT EXISTS may be a safer alternative.

10. Does IN remove duplicate rows?

No. IN only controls which rows qualify. If the underlying query produces duplicate rows, use an appropriate technique such as DISTINCT when deduplication is actually required.

Module 8: Range Filtering with BETWEEN and NOT BETWEEN

Module 8

Range Filtering with BETWEEN and NOT BETWEEN

A step-by-step, hands-on SQL practice lesson — with a live SQL playground

SELECT student_name, grade_level FROM class_room WHERE grade_level BETWEEN 8 AND 9;

After learning how to filter rows with WHERE, I can use BETWEEN when I need a clean way to work with a range of values. In this lesson, I practice both BETWEEN and NOT BETWEEN with numbers, dates, and a simple class_room table. I will build the database step by step, test each query, and use the live playground to see exactly which rows are inside or outside a range.

Introduction

What You'll Learn — and Why Range Filtering Matters

I use range filters whenever I need to ask a question such as “which students are in grades 8 through 9?” or “which records fall between two dates?” The BETWEEN operator makes these questions easy to read, while NOT BETWEEN lets me find values outside the range.

๐ŸŽฏ Objective

By the end of this lesson, you will be able to:

  • Explain how BETWEEN works in SQL.
  • Use BETWEEN to filter numeric values inside an inclusive range.
  • Use NOT BETWEEN to find values outside an inclusive range.
  • Use range filters with dates and understand why date/time boundaries need care.
  • Combine BETWEEN with AND, OR, and other WHERE conditions.
  • Recognize common mistakes and choose clearer range conditions.

⚠️ What to Avoid

Range filters need exact boundaries
  • Do not forget that BETWEEN is inclusive: both boundary values are included.
  • Do not assume NOT BETWEEN includes NULL. A NULL value does not become an ordinary value outside the range.
  • Be careful with date/time columns. A condition such as BETWEEN '2026-08-01' AND '2026-08-31' can be surprising when the column contains times.
  • Do not use a range when a different condition communicates your business rule more clearly.

๐Ÿ’ก Important to Know

The core idea

BETWEEN low AND high means the value is greater than or equal to low and less than or equal to high. NOT BETWEEN low AND high reverses that range condition and keeps values outside the inclusive boundaries.

Requirements

What You'll Need Before Starting

Operating SystemWindows, macOS, Linux, or another operating system that can run MySQL. The SQL syntax in this lesson is the same across these systems.
Database ServerMySQL installed and running. If you need installation help, see How to Install MySQL Step by Step for Beginners.
Optional: XAMPPXAMPP plus phpMyAdmin provides a visual way to run the SQL. See How to Install XAMPP Step by Step for Beginners (Complete Guide 2026).
Prior knowledgeYou should know basic SELECT and WHERE. If you need a refresher, review Module 1: Mastering the SQL SELECT Statement (A Step-by-Step Guide).

No installation is required for the browser playground below. The real practice steps are written for MySQL or phpMyAdmin.

Practice

Step-by-Step Practice: BETWEEN and NOT BETWEEN

I recommend following the steps in order. First I prepare the database, then I test a simple numeric range, and finally I combine range filtering with other conditions and dates.

1 Open MySQL or phpMyAdmin

On Windows, macOS, or Linux, open your MySQL client. If you use XAMPP, start MySQL and open phpMyAdmin. In the terminal, I can connect with:

mysql -u root -p

The basic range-filtering syntax is:

SELECT column1, column2
FROM table_name
WHERE column_name BETWEEN low_value AND high_value;

For the opposite range:

SELECT column1, column2
FROM table_name
WHERE column_name NOT BETWEEN low_value AND high_value;

2 Create a Database and Verify It

I create a separate practice database so my range-filtering exercises stay organized.

CREATE DATABASE module8_between_practice;
SHOW DATABASES;
USE module8_between_practice;

After SHOW DATABASES;, confirm that module8_between_practice appears.

3 Create the class_room Table

Now I create a small classroom table with values that make range filtering easy to see.

CREATE TABLE class_room (
  id INT PRIMARY KEY,
  student_name VARCHAR(80),
  grade_level INT,
  score DECIMAL(5,2),
  status VARCHAR(20),
  room VARCHAR(20)
);

Verify the table structure:

SHOW TABLES;
DESCRIBE class_room;

4 Insert Sample Data

I insert different grade levels and scores so we can test both sides of a range.

INSERT INTO class_room (id, student_name, grade_level, score, status, room) VALUES
(1, 'Dara', 7, 62.50, 'active', 'A101'),
(2, 'Sokha', 8, 74.00, 'inactive', 'A101'),
(3, 'Maly', 8, 81.50, 'active', 'B201'),
(4, 'Vannak', 9, 88.00, 'pending', 'B201'),
(5, 'Lina', 9, 93.50, 'active', 'C301'),
(6, 'Rith', 10, 69.00, 'inactive', 'C301'),
(7, 'Nita', 10, 97.00, 'active', 'D401'),
(8, 'Bora', 11, 55.00, 'pending', 'D401');
SELECT * FROM class_room;

5 Use BETWEEN with Numbers

Suppose I want students in grades 8 through 9. I can write:

SELECT student_name, grade_level
FROM class_room
WHERE grade_level BETWEEN 8 AND 9;

The important detail is that 8 and 9 are included. In other words, this is equivalent to:

SELECT student_name, grade_level
FROM class_room
WHERE grade_level >= 8
  AND grade_level <= 9;
My practice note

When I see BETWEEN 8 AND 9, I mentally read it as “greater than or equal to 8, and less than or equal to 9.” That makes the inclusive boundary easier to remember.

6 Use NOT BETWEEN for Values Outside a Range

Now I reverse the range. If I want students whose grades are outside 8 through 9:

SELECT student_name, grade_level
FROM class_room
WHERE grade_level NOT BETWEEN 8 AND 9;

This is conceptually the same as:

SELECT student_name, grade_level
FROM class_room
WHERE grade_level < 8
   OR grade_level > 9;

7 Filter a Score Range

BETWEEN is not limited to integer columns. I can use it with decimal scores too.

SELECT student_name, score
FROM class_room
WHERE score BETWEEN 80 AND 90
ORDER BY score;

And I can find scores outside that interval:

SELECT student_name, score
FROM class_room
WHERE score NOT BETWEEN 80 AND 90
ORDER BY score;

8 Combine a Range with Another Condition

Real queries often need more than one filter. For example, I can find active students with scores from 70 through 95.

SELECT student_name, score, status
FROM class_room
WHERE status = 'active'
  AND score BETWEEN 70 AND 95
ORDER BY score DESC;

I can also combine NOT BETWEEN with another condition:

SELECT student_name, score, status
FROM class_room
WHERE status = 'active'
  AND score NOT BETWEEN 80 AND 90
ORDER BY score;

9 Practice with Dates and Understand the Boundary

Range filtering is also useful for dates. For a DATE column, this is straightforward:

SELECT *
FROM your_table
WHERE enrollment_date BETWEEN '2026-08-01' AND '2026-08-31';

For a DATETIME column, I need to think about the time portion. A safer pattern for the whole month is often:

WHERE created_at >= '2026-08-01'
  AND created_at < '2026-09-01'

This avoids accidentally excluding records later on August 31 when the column stores a time as well as a date.

Troubleshooting

5 Common Problems and Solutions

Problem 1: I thought BETWEEN excluded the boundary values

I expected BETWEEN 8 AND 9 to return only values greater than 8 and less than 9.

SolutionRemember that BETWEEN is inclusive. BETWEEN 8 AND 9 includes both 8 and 9. If you need strict boundaries, use > and < explicitly.

Problem 2: NOT BETWEEN does not return NULL rows

I may think a NULL is “outside the range,” but SQL does not treat NULL as a normal number.

SolutionIf NULL should be included in the result, say so explicitly, for example: WHERE score NOT BETWEEN 80 AND 90 OR score IS NULL.

Problem 3: My date query misses records from the last day

This commonly happens when the column is a DATETIME rather than a plain DATE.

SolutionFor a complete date interval, consider a half-open range such as created_at >= '2026-08-01' AND created_at < '2026-09-01'.

Problem 4: I used BETWEEN with values in the wrong order

A condition such as BETWEEN 90 AND 80 does not mean “between 80 and 90” in the normal way.

SolutionPut the lower boundary first and the higher boundary second: BETWEEN 80 AND 90.

Problem 5: My combined AND/OR range query is confusing

Once several conditions are combined, it can become difficult to see which part is supposed to be inside or outside the range.

SolutionUse parentheses for grouped logic, keep each condition on its own line, and test each condition separately before combining them.

Conclusion

What I Want You to Remember

The main lesson I take from Module 8 is simple: BETWEEN is a readable way to filter values inside an inclusive range, while NOT BETWEEN filters values outside that range.

My biggest habit here is checking the boundaries before I run the query. I ask: Are the lower and upper values supposed to be included? For numeric columns, BETWEEN is often very clear. For date/time columns, I also check whether the column stores only a date or a date plus a time.

Expected result from this lesson

You should now be able to use BETWEEN and NOT BETWEEN confidently, explain their inclusive boundaries, combine them with other filters, and avoid common date/time and NULL mistakes.

Next lesson: continue building SQL conditions by combining logical operators and more advanced filtering patterns.

Homework

Homework & Quiz

๐Ÿ“ Homework Task

Using the class_room table, write these queries yourself before checking the live playground:

  1. Find students whose grade level is between 8 and 10.
  2. Find students whose grade level is not between 8 and 9.
  3. Find students whose score is between 75 and 95.
  4. Find active students whose score is not between 80 and 90.
  5. Write a query for a hypothetical created_at DATETIME column that returns every record from August 2026.

๐Ÿงช Quiz: Test Your Understanding (10 Questions)

Pick one answer per question, then click Submit to see your score instantly.

1. What does BETWEEN 8 AND 9 include?

2. Which syntax correctly filters a score from 80 to 90?

3. What does NOT BETWEEN 80 AND 90 mean?

4. Is BETWEEN inclusive in SQL?

5. What is a useful equivalent for score BETWEEN 80 AND 90?

6. Does NOT BETWEEN automatically include NULL values?

7. Which is generally safer for a full month on a DATETIME column?

8. Which order should the BETWEEN boundaries normally have?

9. Which condition finds active students with scores between 70 and 95?

10. What is the main idea of Module 8?

0 / 10

Try It Live

๐Ÿงช Live SQL Playground

This browser playground uses SQLite through WebAssembly. It is designed to practice the range-filtering logic in this lesson; use your real MySQL server for MySQL-specific testing.

class_roomid INTEGER PK
student_name TEXT
grade_level INTEGER
score REAL
status TEXT
room TEXT
Loading SQL engine…
Run a query to see results here.

FAQ

Frequently Asked Questions

1. What does BETWEEN do in SQL?

BETWEEN filters values that fall within a range, including both boundary values.

2. Is BETWEEN inclusive?

Yes. BETWEEN low AND high includes both low and high.

3. What does NOT BETWEEN mean?

It returns values outside the inclusive range specified by the two boundaries.

4. Can BETWEEN work with decimal numbers?

Yes. It can be used with numeric values such as integer and decimal columns.

5. Can BETWEEN work with dates?

Yes. It can filter date values, but DATETIME columns require extra care because the time component is part of the value.

6. Does NOT BETWEEN include NULL values?

Not automatically. NULL needs explicit handling with IS NULL if your business rule requires it.

7. What is the difference between BETWEEN and IN?

BETWEEN describes a continuous range, while IN checks membership in a list of specific values.

8. Can I combine BETWEEN with AND?

Yes. For example, status = 'active' AND score BETWEEN 70 AND 95 applies both conditions.

9. What happens if I reverse the BETWEEN boundaries?

Use the lower boundary first and the higher boundary second. Do not rely on reversed boundaries to express a normal range.

10. Is the live playground the same as MySQL?

No. The playground uses SQLite compiled to WebAssembly. It is for browser practice; use MySQL or phpMyAdmin for MySQL-specific testing.