SELECT: Choosing Your Columns

You have written SELECT * many times by now. It works, but it’s a bit like asking for everything in the fridge when you just want milk. This week, we will look at the SELECT clause and see that it does more than just pick columns. It transforms your output. Previously, we looked closely at the FROM clause, which tells the database where the query will find the data. The SELECT clause defines which columns will be returned, and you can reshape data on the way out. ...

February 16, 2026 · 4 min · Jamal Hansen

FROM: Where Your Data Lives

We have come a long way over the last five posts, but we are just getting started. So far, we have explored concepts that will help us along our journey, but haven’t talked a whole lot about SQL itself. We have seen some basic SQL that uses a couple of keywords, SELECT and FROM, but we haven’t looked very closely at what these do. Let’s do that now, starting with FROM. ...

February 9, 2026 · 3 min · Jamal Hansen
SQL Thinks in Sets, Not Loops

SQL Thinks in Sets, Not Loops

Remember back when we started, I mentioned SQL was difficult because of how I was thinking? I was asking it to perform steps to return data. This didn’t work because SQL uses a declarative syntax that describes the final result. Until I realized this, SQL felt hard. Let’s explore this concept further. Working with lists and loops When you work with lists in Python, one of the first tools you reach for is the for loop. The for loop is great because it lets you take every item in the list and apply some logic to it, one at a time. It might look something like this. ...

February 2, 2026 · 4 min · Jamal Hansen
Don't forget to save! Persisting your DuckDB database

Don't forget to save! Persisting your DuckDB database

I still remember losing schoolwork and video game progress because I forgot to save. That sinking feeling when hours of work vanish because you were too caught up in the flow to pause and save. In our last post, we created a customer database and generated 500 rows of fake data. Our in-memory database has the same problem: when Python exits, all that data vanishes: import duckdb con = duckdb.connect(':memory:') con.execute("CREATE TABLE customers (id INT, name VARCHAR)") con.execute("INSERT INTO customers VALUES (1, 'Alice')") print(con.execute("SELECT * FROM customers").fetchdf()) # Script ends... and the data is gone forever A database is supposed to provide persistent storage, isn’t it? Let’s fix that with one small change. ...

January 26, 2026 · 3 min · Jamal Hansen
Generate Practice Data with faker

Generate Practice Data with faker

Last week, we got DuckDB running with three hardcoded rows. That got us started, but three rows? You can eyeball that. Let’s generate hundreds of realistic customers and build a dataset worth exploring. Python has the perfect tool: faker. It’s a library that generates realistic fake data: names, emails, addresses, dates, and anything else you’d find in a real database. Let’s use it to build a dataset we can explore for the rest of this series. ...

January 19, 2026 · 4 min · Jamal Hansen
I know Python; Why learn SQL

I know Python; Why learn SQL

SQL and Python solve different problems with data. Python tells the computer what to do, step by step. SQL describes the data you want and lets the database figure out how to get it. As a Python developer, learning SQL means you’ll write better pandas queries, know when to push work to the database instead of pulling everything into memory, and understand what your ORM is actually doing under the hood. ...

January 5, 2026 · 3 min · Jamal Hansen