AD JB Toolbox 01 EN

MariaDB Tutorial / Filter Rows with WHERE, AND, OR, IN, BETWEEN, and LIKE

WHERE keeps rows whose condition evaluates to true. Combine comparisons with AND and OR, and use IN, BETWEEN and LIKE for lists, ranges and text patterns; check parentheses and NULL behavior so the filter selects the intended rows.

Define the condition separately from the output columns

SELECT product_name chooses what to display; WHERE price >= 8000 chooses which rows qualify. A false or unknown condition does not pass WHERE. Compare numeric columns with appropriate numeric values and strings with quoted strings rather than relying on unnecessary implicit conversion. Apply the NULL rules in Compare NULL Correctly with IS NULL and COALESCE to missing values, then separately define result order and size using Sort and Paginate Results with ORDER BY and LIMIT.

Operator Meaning Condition to consider
=, <> Equal, not equal NULL needs separate handling
>, >=, <, <= Ordered comparison Decide whether to include the boundary
AND / OR Both conditions / either condition Use parentheses to show intent
IN Matches a listed value Validate the list contents
BETWEEN Inclusive range Both endpoints are included
LIKE Text pattern Distinguish wildcard characters from literals

Check the MariaDB documentation for the syntax and conditions used here: LIKE, operator precedence.

Prepare the comparison data

Connect to the learning server as course_user and select shopcourse. The command-line and UTF-8 SQL-file guide explains how to save the code as a UTF-8 file and execute it with SOURCE C:/mariadb-lab/lesson.sql;, replacing the path with the actual file. Run SQL inside the MariaDB client, rather than at the operating-system prompt.

Check SELECT VERSION(), DATABASE(); and SHOW TABLES; before creating products_15_lab. These names belong only to this exercise. If they exist, inspect their definitions and rows first; remove them only when you have established that they are disposable exercise objects. Do not replace existing application tables.

USE shopcourse;
CREATE TABLE products_15_lab (
  product_id INT NOT NULL AUTO_INCREMENT,
  product_name VARCHAR(100) NOT NULL,
  category VARCHAR(30) NOT NULL,
  price DECIMAL(10,2) NOT NULL,
  stock INT NOT NULL DEFAULT 0,
  note VARCHAR(100) NULL DEFAULT NULL,
  PRIMARY KEY (product_id),
  CONSTRAINT ck_p15_price CHECK (price >= 0),
  CONSTRAINT ck_p15_stock CHECK (stock >= 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO products_15_lab
  (product_id, product_name, category, price, stock, note)
VALUES (1, '노트', '문구', 3500.00, 20, NULL),
  (2, '볼펜', '문구', 1500.00, 0, ''),
  (3, '머그컵', '생활', 8000.00, 12, '선물 포장'),
  (4, '스탠드', '생활', 25000.00, 5, NULL),
  (5, '파일', '문구', 1500.00, 50, ''),
  (6, '케이블', '전자', 8000.00, 0, '호환 확인');

The SQL retains the original Korean sample strings to exercise UTF-8 consistently. Product identifiers 1–6 represent a notebook, pen, mug, lamp, folder and cable; their category strings mean stationery, household and electronics. Enter the string literals as shown, use the identifiers when comparing results, and save the file with UTF-8 encoding.

Stationery contains IDs 1, 2 and 5; household contains 3 and 4; electronics contains 6. Zero-stock products are 2 and 6. Change one condition at a time against this fixed fixture so the reason for each result difference is visible.

Compare boundaries and AND/OR parentheses

SELECT product_id, product_name, price FROM products_15_lab
WHERE price >= 8000 ORDER BY product_id;

The inclusive 8000 comparison returns IDs 3, 4 and 6. Changing >= to > removes the two products priced exactly 8000 and leaves ID 4. Restore the original condition after comparing. Finding the highest-priced product additionally needs an ordering and a result-size rule.

SELECT product_id FROM products_15_lab
WHERE (category = '문구' OR category = '생활') AND stock > 0
ORDER BY product_id;
SELECT product_id FROM products_15_lab
WHERE category = '문구' OR category = '생활' AND stock > 0
ORDER BY product_id;

The parenthesized query returns 1, 3, 4 and 5: stationery or household products that have stock. Without the parentheses, AND binds more tightly than OR, so the zero-stock stationery product 2 is also included. Write the intended grouping explicitly instead of asking readers to reconstruct precedence.

Use IN lists and inclusive BETWEEN ranges

SELECT product_id FROM products_15_lab
WHERE category IN ('문구', '전자') ORDER BY product_id;
SELECT product_id FROM products_15_lab
WHERE price BETWEEN 1500 AND 8000 ORDER BY product_id;

The IN example returns 1, 2, 5 and 6. BETWEEN 1500 AND 8000 returns 1, 2, 3, 5 and 6, including both endpoint prices. For this numeric condition it is equivalent to price >= 1500 AND price <= 8000.

A date-and-time endpoint needs more care. An upper endpoint at midnight excludes later times on that day. A start-inclusive, next-day-exclusive range is often easier to express correctly; this exercise uses numeric prices to make the endpoints unambiguous.

Distinguish LIKE wildcards from literal characters

SELECT product_id, product_name FROM products_15_lab
WHERE product_name LIKE '%컵%' ORDER BY product_id;
SELECT product_id, product_name FROM products_15_lab
WHERE product_name LIKE '__' ORDER BY product_id;

The percent wildcard matches zero or more characters and an underscore matches one character. The Korean substring pattern selects the mug, ID 3. Two underscores select the two-character Korean product names at IDs 1, 2 and 5. Character counts are not UTF-8 byte counts.

SELECT '진행률 10%' LIKE '%!%%' ESCAPE '!' AS has_percent;

The literal-percent example declares ! as the escape character, so !% means a percent sign rather than a wildcard; has_percent is 1. Parameterize user-provided values and decide separately whether a user’s percent or underscore should act as a wildcard. Collation affects text comparisons, including case behavior.

Investigate empty or overbroad results

Display the primary key and every filtered column, then add conditions gradually. Check AND versus OR, inclusive boundaries, unexpected spaces and actual stored types. Before reusing a condition in UPDATE or DELETE, inspect its selected rows. Use IS NULL instead of = NULL, and review the NULL comparison guide before using an exclusion list that may contain NULL.

Before repeating the exercise, inspect the selected database, actual table definitions and stored rows, and back up anything that must be kept. Drop only this article’s disposable practice objects, with child tables before their referenced parents. DROP TABLE removes both definitions and rows and cannot be undone by an ordinary ROLLBACK; keep cleanup separate from transaction experiments.

DROP TABLE shopcourse.products_15_lab;
More in This Category
MariaDB Tutorial / Use Subqueries, EXISTS, and NOT EXISTS

MariaDB Tutorial / Use Subqueries, EXISTS, and NOT EXISTS

Choose scalar and existence subqueries according to the result needed. Compare paid-order customers and absent-order customers, inspect correlation keys and avoid NULL-related exclusion assumptions.

MariaDB Tutorial / Build, Secure, Back Up, and Verify an Order Database

MariaDB Tutorial / Build, Secure, Back Up, and Verify an Order Database

Complete an order-database workflow using constrained tables, a limited app account and a checked stock transaction. Define and compare committed-state backup and restoration criteria, including denied operations.

MariaDB Tutorial / Save Reusable Query Definitions with VIEW

MariaDB Tutorial / Save Reusable Query Definitions with VIEW

Create an INVOKER view for paid-order totals, inspect its definition and observe transaction changes. Review security, updateability, dependencies and the difference between a view and stored result data.

MariaDB Tutorial / Understand Replication, Lag, Errors, and Failover

MariaDB Tutorial / Understand Replication, Lag, Errors, and Failover

Prepare a two-server local Compose lab and interpret replication status, lag and errors. Observe apply-thread pause/resume behavior and distinguish replication from backup and controlled failover.

MariaDB Tutorial / Build and Reconcile Monthly Sales, Customer Totals, and Unsold Products

MariaDB Tutorial / Build and Reconcile Monthly Sales, Customer Totals, and Unsold Products

Create three related MariaDB reports from one order fixture, retain nonbuyers and find products without paid sales. Reconcile monthly and customer amounts and inspect join, status and date boundaries.

MariaDB Tutorial / Calculate Running Totals and Compare Rows with LAG and LEAD

MariaDB Tutorial / Calculate Running Totals and Compare Rows with LAG and LEAD

Calculate running totals, LAG and LEAD, then compare ROWS and RANGE with tied timestamps. Verify how filtering before or after accumulation changes a period report.

MariaDB Tutorial / Restore a Backup into a Separate Database and Verify It

MariaDB Tutorial / Restore a Backup into a Separate Database and Verify It

Review a SQL dump, restore it into a verified empty database and compare object definitions, rows and goods totals. Handle source-file errors, compatibility and partial-restoration states explicitly.

MariaDB Tutorial / Create Users and Grant Only Required Privileges

MariaDB Tutorial / Create Users and Grant Only Required Privileges

Create a table-scoped MariaDB reader, inspect its real account identity, test allowed reads and denied operations, then verify revocation and review account dependencies before cleanup.

MariaDB Tutorial / Connect Python to MariaDB and Use Parameterized Queries

MariaDB Tutorial / Connect Python to MariaDB and Use Parameterized Queries

Use a complete PyMySQL program to connect, insert, select, commit, and roll back. Keep apostrophes, Unicode, and injection-shaped inputs as values, and restrict dynamic sorting through an identifier allowlist.

MariaDB Tutorial / Back Up an InnoDB Database with mariadb-dump

MariaDB Tutorial / Back Up an InnoDB Database with mariadb-dump

Create a scoped mariadb-dump backup with explicit consistency and file options. Check errors and hashes, inventory additional objects and define a separate-database restoration baseline.