Skip to content

SQL from Python (pandas + sqlite3)

A common workflow:

  1. Use SQL to extract/aggregate data efficiently
  2. Load into pandas
  3. Visualize/model

SQLite is file-based and great for learning.

Create SQLite DB
import sqlite3
import pandas as pd
 
conn = sqlite3.connect("demo.db")
 
# Example: create a table
conn.execute("""
CREATE TABLE IF NOT EXISTS users (
  user_id INTEGER PRIMARY KEY,
  country TEXT,
  plan TEXT
)
""")
 
conn.execute("DELETE FROM users")
conn.executemany(
    "INSERT INTO users(user_id, country, plan) VALUES (?, ?, ?)",
    [(1, "IN", "free"), (2, "IN", "pro"), (3, "US", "pro")],
)
conn.commit()
Read SQL into pandas
import pandas as pd
 
q = """
SELECT country, COUNT(*) AS users
FROM users
GROUP BY country
"""
 
df = pd.read_sql_query(q, conn)
print(df)
  • Keep SQL in triple-quoted strings or .sql files.
  • Parameterize user inputs (avoid SQL injection).
  • Version-control your analysis scripts.

McKinney’s Python for Data Analysis covers exactly this workflow in §6.4, “Interacting with Databases.” There are two paths, and it’s worth seeing both:

diagram SQL -> DataFrame, two paths mermaid
The raw sqlite3 driver returns tuples you must pair with column names yourself; pandas.read_sql does that munging for you.

The manual way (what the book shows first)

Section titled “The manual way (what the book shows first)”
Cursor to DataFrame, by hand
import sqlite3
import pandas as pd
 
conn = sqlite3.connect(":memory:")
conn.execute("CREATE TABLE test (a TEXT, b TEXT, c REAL, d INTEGER)")
data = [
    ("Atlanta", "Georgia", 1.25, 6),
    ("Tallahassee", "Florida", 2.6, 3),
    ("Sacramento", "California", 1.7, 5),
]
conn.executemany("INSERT INTO test VALUES (?, ?, ?, ?)", data)
conn.commit()
 
cursor = conn.execute("SELECT * FROM test")
rows = cursor.fetchall()
columns = [col[0] for col in cursor.description]
 
df = pd.DataFrame(rows, columns=columns)
print(df)
text
             a           b     c  d
0      Atlanta     Georgia  1.25  6
1  Tallahassee     Florida  2.60  3
2   Sacramento  California  1.70  5
read_sql_query does the munging for you
df = pd.read_sql_query("SELECT * FROM test", conn)
print(df)

Same result, one line. read_sql_query works with a plain sqlite3 connection; the book’s pd.read_sql example additionally shows connecting through SQLAlchemy (sqla.create_engine), which is the more general path once you move beyond SQLite to Postgres, MySQL, or a warehouse.

Exercise 1 – Build column names from cursor.description

Section titled “Exercise 1 – Build column names from cursor.description”

Exercise 2 – pd.DataFrame from rows + columns

Section titled “Exercise 2 – pd.DataFrame from rows + columns”

Exercise 3 – The read_sql_query shortcut

Section titled “Exercise 3 – The read_sql_query shortcut”

Put everything from this phase together in the SQL Mini Project (Build a KPI Dashboard Query Set) — a small, reusable pack of queries you can point at any similar dataset.

pch.coffeeTagline

pch.coffeeCta

pch.feedbackHeading

pch.feedbackSubheading