This guide walks through common string manipulation tasks using SQL queries on our sample datasets.
By default the sqlite3 interactive environment won't include column names in its output. To activate display of the column names use the command .headers on which will make your output more readable.
For each task this guide provides both a description of a realistic string manipulation task and code in Python (Pandas) that will produce the desired result. Your task is to write SQL queries that accomplish the same result.
Task: Extract manufacturer names from car names in the mpg dataset. The manufacturer is always the first word in the car name.
Here's how we'd do it in Python:
>>> df = sns.load_dataset('mpg')
>>> df['name'].str.split().str[0].head()
0 chevrolet
1 buick
2 plymouth
3 amc
4 ford
Name: name, dtype: objectProposed solution here:
SELECT DISTINCT
SUBSTR(name, 1, INSTR(name || ' ', ' ') - 1) as manufacturer
FROM mpg
ORDER BY manufacturer;Task: Create a standardized view of the data where origin is in UPPERCASE and manufacturer (first word of name) is in Title Case.
Here's how we'd do it in Python:
>>> df = sns.load_dataset('mpg')
>>> df.assign(
... origin_upper=df['origin'].str.upper(),
... maker_title=df['name'].str.split().str[0].str.title()
... ).head()
origin origin_upper maker_title
0 usa USA Chevrolet
1 usa USA Buick
2 usa USA Plymouth
3 usa USA Amc
4 usa USA FordProposed solution here:
SELECT
name,
UPPER(origin) as origin_upper,
UPPER(SUBSTR(name, 1, 1)) || UPPER(SUBSTR(name, 2, INSTR(name || ' ', ' ') - 2)) as maker_title
FROM mpg limit 5;Task: Find all cars that have either 'custom' or 'deluxe' in their names (case insensitive).
Here's how we'd do it in Python:
>>> df = sns.load_dataset('mpg')
>>> df[df['name'].str.lower().str.contains(r'custom|deluxe')]
name mpg cylinders displacement horsepower \
27 ford galaxie 500 custom 14.0 8 351.0 153.0
82 ford custom 500 15.5 8 351.0 142.0
89 chevrolet impala custom 13.0 8 350.0 165.0
165 ford custom 17.0 6 250.0 100.0 Proposed solution here:
SELECT
name,
mpg,
cylinders,
displacement,
horsepower
FROM mpg
WHERE LOWER(name) LIKE '%custom%'
OR LOWER(name) LIKE '%deluxe%'
ORDER BY name;Task: Find all cars whose names include a number (like '98' or '300').
Here's how we'd do it in Python:
>>> df = sns.load_dataset('mpg')
>>> df[df['name'].str.contains(r'\d')][['name', 'mpg', 'cylinders', 'displacement', 'weight']].head(3)
name mpg cylinders displacement weight
1 buick skylark 320 15.0 8 350.0 3693
5 ford galaxie 500 15.0 8 429.0 4341
11 plymouth 'cuda 340 14.0 8 340.0 3609Proposed solution here:
SELECT
name,
mpg,
cylinders,
displacement,
weight
FROM mpg
WHERE name GLOB '*[0-9]*'
ORDER BY name;Task: Create a full description combining year, origin, and name into a readable format.
Here's how we'd do it in Python:
>>> df = sns.load_dataset('mpg')
>>> df.assign(
... description=df['model_year'].astype(str) + ' ' +
... df['origin'].str.upper() + ' ' +
... df['name']
... ).head()
description
0 70 USA chevrolet chevelle malibu
1 70 USA buick skylark 320
2 70 USA plymouth satellite
3 70 USA amc rebel sst
4 70 USA ford torinoAlternatively a simpler approach would also work:
>>> (df['model_year'].astype(str) + ' ' + df['name'] + ' ' + df['origin']).head(3)Proposed solution here:
SELECT
model_year || ' ' ||
UPPER(origin) || ' ' ||
name as description
FROM mpg
LIMIT 5;Task: Clean car names by removing extra spaces and standardizing format (e.g., convert multiple spaces to single space).
Here's how we'd do it in Python:
>>> df = sns.load_dataset('mpg')
>>> # Adding some extra spaces to demonstrate cleaning
>>> df['name'] = df['name'].apply(lambda x: ' ' + x + ' ')
>>> df['name'].str.strip().str.replace(r'\s+', ' ').head()
0 chevrolet chevelle malibu
1 buick skylark 320
2 plymouth satellite
3 amc rebel sst
4 ford torino
Name: name, dtype: objectProposed solution here:
SELECT
TRIM(REPLACE(REPLACE(name, ' ', ' '), ' ', ' ')) as cleaned_name
FROM mpg
LIMIT 5;Task: Categorize car names by length into 'Short' (< 15 chars), 'Medium' (15-25 chars), or 'Long' (> 25 chars).
Here's how we'd do it in Python:
>>> df = sns.load_dataset('mpg')
>>> def length_category(name):
... length = len(name)
... if length < 15:
... return 'Short'
... elif length <= 25:
... return 'Medium'
... else:
... return 'Long'
>>> df.assign(name_category=df['name'].apply(length_category)).head(10)
name name_category
0 chevrolet chevelle malibu Medium
1 buick skylark 320 Medium
2 plymouth satellite Medium
3 amc rebel sst Short
4 ford torino Short
5 ford galaxie 500 MediumProposed solution here:
SELECT
name,
LENGTH(name) as name_length,
CASE
WHEN LENGTH(name) < 15 THEN 'Short'
WHEN LENGTH(name) <= 25 THEN 'Medium'
ELSE 'Long'
END as name_category
FROM mpg
LIMIT 10;- Enter SQLite command line:
sqlite3 sandbox.db- For better output formatting, run these commands first:
.mode column
.headers on- To exit SQLite:
.quit- SUBSTR(X,Y,Z) extracts a substring from X starting at position Y with length Z
- INSTR(X,Y) finds the first occurrence of Y in X
- LENGTH(X) returns the number of characters in X
- TRIM(X) removes whitespace from both ends of X
- UPPER(X) and LOWER(X) change the case of X
- || is used for string concatenation
- REPLACE(X,Y,Z) replaces all occurrences of Y in X with Z
- Always consider case sensitivity in your comparisons
- Use TRIM() when comparing or matching strings that might have extra spaces
- Combine multiple string functions to achieve more complex transformations
- Test your queries with edge cases (empty strings, NULL values, etc.)
- Use appropriate wildcards (% for LIKE, * for GLOB) based on your needs