Lists, ranges and patterns
Problem
Three cities, three ORs
The courier company for the north-east and the coast serves Varna, Burgas and Ruse. You need the customers from those cities:
It works, but with ten cities the condition becomes a line of ORs where it is easy to miss one.
The idea
IN: one from the list
IN checks whether a value is in a list:
The same result, and the list reads at a glance. NOT IN is the opposite: everything except the listed ones.
The idea
BETWEEN: between two limits
BETWEEN a AND b means “from a to b”, including a and b:
Dates in the database are text like 2026-03-31. Such text sorts the way dates do, so BETWEEN works for them too. The orders from the first quarter of 2026:
More precisely, if you are curious
If the date also has a time (2026-03-31 18:20), BETWEEN '2026-01-01' AND '2026-03-31' misses 31 March after midnight, because '2026-03-31 18:20' comes after '2026-03-31'. Then it is safer to write ordered_at >= '2026-01-01' AND ordered_at < '2026-04-01'.
Try it
The open orders
Show the number, date and status of the orders that are neither delivered (delivered) nor cancelled (cancelled).
Solution
SELECT id, ordered_at, status FROM orders
WHERE status NOT IN ('delivered', 'cancelled');WHERE status NOT IN ('delivered', 'cancelled'). 32 orders are waiting: new, paid or shipped.
The idea
LIKE: by part of the text
LIKE compares with a pattern. In the pattern, % means “any text, even none”, and _ means “exactly one character”.
'%bread%' finds every name with “bread” somewhere in it. 'bread%' would look for names that start with “bread”, and '%bread' for names that end with it.
See it
Upper and lower case
Which products start with “b”? Run:
“Butter roll”, “Butter” and “Bananas” come out, although they start with a capital B. In SQLite LIKE ignores case, but only for Latin letters. For Cyrillic, a capital letter and its small form are two different characters: on the Bulgarian pages of this course, a search for names starting with a small Cyrillic “b” finds nothing.
More precisely, if you are curious
Databases differ here. In PostgreSQL LIKE always cares about case, and ILIKE does not, for any alphabet. In MySQL it depends on the text comparison setting (collation), and usually case is ignored. If a search has to work for every alphabet, SQLite needs an extension (ICU), or you keep a separate column with the text in lower case.
Try it
The milk
Show the name and price of the products with “milk” in the name.
Solution
SELECT name, price FROM products WHERE name LIKE '%milk%';WHERE name LIKE '%milk%': the fresh milk. Yoghurt is a milk product, but the word is not in its name. A search finds the text, not the meaning.
Exercise
Two tasks
1. The orders from summer 2026 (June, July, August): number, customer and date.
The orders between 1 June and 31 August 2026:
Solution
SELECT id, customer_id, ordered_at FROM orders
WHERE ordered_at BETWEEN '2026-06-01' AND '2026-08-31';WHERE ordered_at BETWEEN '2026-06-01' AND '2026-08-31'. It also works with >= and <=.
2. The customers whose name starts with “M”: name and city.
The customers whose name starts with “M”:
Solution
SELECT name, city FROM customers WHERE name LIKE 'M%';WHERE name LIKE 'M%'. Maria and Martin.
Test