High Performance
SQLite
Introduction
Introduction to this course
Introduction to SQLite
SQLite is safe
It's just a file
Running SQLite locally
Good uses for SQLite
SQLite's limitations
The documentation
SQLite Internals
SQLite's structure
SQLite's file format
Dot commands
Pragmas
Virtual tables
Schema
Flexible types
Types
Strict types
Dates
Booleans
Floating point
Rowid tables
Auto increments
Without rowid
Generated columns
Optimizing SQLite
Locking
Rollback mode
WAL mode
WAL vs Journal benchmarks
Busy timeout
Transaction modes
Vacuum
Analyze & Optimize
Suggested pragmas
Faster inserts
Indexes
Introduction to indexes
B+ trees
Primary, secondary, and clustered indexes
Without rowid tables
Benchmarking without rowid tables
Imposter tables
Primary key data types
Where to add indexes
Index selectivity
Composite indexes
Composite ordering
Covering indexes
Partial indexes
Indexes on expressions
Automatic indexes
Duplicate indexes
Indexing joins
Advanced SQL
Explain
Index obfuscation
Joins
Subqueries
Unions
CTEs
Recursive CTEs
Window functions
Dealing with NULLs
Row value syntax
Indexed sorting
Upserts
Returning
Aggregates
Triggers
Operating SQLite
Altering schema
Altering schema with tools
Multi-database
Multi-tenancy
Backups
Exports
How to corrupt SQLite
Advanced JSON
Intro to JSON
JSON vs. JSONB
Argument types: path, value, JSON
JSON5
Valid JSON
Creating JSON objects + arrays
JSON Extraction
Updating JSON
JSON aggregates
JSON table functions
Indexing JSON
Full Text Search
Creating FTS tables
Performing searches
Ranking results
Highlighting matches
Bonus Interviews
DHH discusses SQLite in Ruby on Rails
Distributed SQLite with Litestream and LiteFS
Offline-first, multiplayer SQLite
Production SQLite with Turso and libSQL
Migrating from Postgres to SQLite with Kent C. Dodds
Ruby on Rails with SQLite
Moving from Redis to SQLite with Mike Buckbee
Locked video

Please purchase the course to watch this video.

Video thumbnail
Advanced SQL
CTEs

Full Course

$
179
$229
USD, one-time fee
I went from near 0 to 100 in less than two weeks with this course. If you want to be a SQLite wizard, and just want to up-level your SQL skills in general, this is definitely the course for you.
Anthony Bullard
Anthony Bullard

SQLite for Production

Build with and integrate SQLite into your production applications.

Test Data

I've made my test data available for you to use and follow along.

Download
or
Use on Turso

Summary

I learned about CTEs, which help organize and boost the performance of SQL queries by treating complex queries as temporary tables. By using CTEs, I can write cleaner and more efficient queries, especially when joining or unioning data. This method is also beneficial in applications with ORM systems, as it improves query management and execution.

Video Transcript

Hopefully, you're getting more and more comfortable with accessing your data, whether that's side by side, over under, filtering based on related, whatever it is. Now we're gonna talk about CTEs, which is a nice way to logically and structurally organize your queries, but can also have performance benefits as well. Before we do that, let's go back to our example from earlier where we are, joining up we're joining up or we're rather we're unioning these two queries. So if we run that, we get the 2 Aaron Francis's there. And, I did show you that you could do something like select star from this as temp and that will give you the same thing again.

This starts to get a little bit unwieldy. We kinda wanna, what we're doing is we're addressing this as a table. And when you have multiple when you have multiple conditions like this and you're building up this really complicated query as you go, it might make more sense to refactor that into a CTE. So let me copy this guy out and what you can do is you can say with table name as and then you open parenthesis and you can do, we're gonna put something in here but let's just do select 1. And then down here you say select star from table name.

And there's your one right there. So in our case, we're gonna name this, let's just call this users all. And then coming down here, notice we don't put a semicolon here. We're gonna say users all. So select star from users all and then in here we put our subquery or rather our 2 queries that we're unioning together to create this users all table and that gives us the 2 Aaron Francis's.

Likely, it's gonna look something more like this where you would take that where statement and come out here and say where email equals Aaron Francis. So here you're just reconstructing archived users and you're putting them together and then you're treating it as if it is a regular table which is really, really nice. You can keep going. So you can say with users, Erin as select star it's this. Select star from users all, where the email is my email, and then we can say from users aaron and we get we need a comma here.

We get the we don't need a with there. We get the same result. Forgive me on the syntax. So you have your CTEs all declared at the top and they can rely on each other. They can rely on each other and you can just keep going.

And this is a really good way to logically clean up some of your more complicated queries and to be able to reuse them. So you can imagine on the ORM side, so if you have an application that has an ORM, I love ORMs. Please use ORMs. They're awesome. You can imagine declaring this table and then just running your ORM across users all.

And so that's a good that's a good way to build up, what could be temporary or intermediate tables and then operate on them as if they're full on tables. Another great benefit of CTEs is that it can prevent SQLite from running a subquery multiple same subquery, it can make a lot of sense to pull that up to a CTE and have it run that CTE one time and then reference it as many times as you want. So it's not only for organization, although it is great for organization, it can also be a performance boost if you're referencing it multiple times and you pull it out to the top.