Skip to content

Commit e81af3f

Browse files
committed
Created SQL blog post, removed features section
1 parent c65611c commit e81af3f

File tree

4 files changed

+169
-43
lines changed

4 files changed

+169
-43
lines changed

public/assets/practiceSQL.png

1.5 MB
Loading
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
---
2+
title: "Keeping Your SQL Skills Sharp: How to Get Databases Fast"
3+
date: "2025-09-21"
4+
summary: "Want to practice SQL without wasting time on fake data? Here's how to spin up real sample databases in PostgreSQL and build your query-writing fluency."
5+
description: "Learn how to set up sample databases like Northwind, Pagila, and Chinook in PostgreSQL for SQL practice. Perfect for developers who want to sharpen their database skills with realistic datasets and relationships."
6+
tags: ["SQL", "PostgreSQL", "Database", "Development"]
7+
featured: true
8+
readTime: 6
9+
image: "/assets/practiceSQL.png"
10+
author: "David Martin"
11+
canonicalURL: "https://djmtech.dev/blog/keeping-your-SQL-skills-sharp"
12+
---
13+
14+
Most of us know the feeling: you want to brush up on SQL — maybe try out a new join, test a reporting query, or just flex your window functions — but you don't want to waste half your Saturday cobbling together fake data. You want to jump into the fun part: **writing queries**.
15+
16+
Whether you're preparing for a technical interview, learning new SQL features, or just want to stay sharp between projects, having realistic sample data makes all the difference.
17+
18+
The good news is there are several tried-and-true sample databases floating around GitHub that are _perfect_ for practice. And with just a couple of terminal commands, you can spin them up in PostgreSQL and have your own personal SQL gym.
19+
20+
---
21+
22+
## 🏋️‍♀️ The Repos You’ll Want 🏋️‍♀️
23+
24+
Here are three of the classics, all free and open source:
25+
26+
### 1. **[Northwind](https://github.com/pthom/northwind_psql)** - 📊 Classic Business Database
27+
28+
```bash
29+
git clone https://github.com/pthom/northwind_psql
30+
```
31+
32+
The famous Microsoft sample database, ported to PostgreSQL. Perfect for practicing business queries with customers, orders, products, and suppliers.
33+
34+
### 2. **[Pagila](https://github.com/devrimgunduz/pagila)** - 📀 DVD Rental System
35+
36+
```bash
37+
git clone https://github.com/devrimgunduz/pagila
38+
```
39+
40+
Based on the Sakila DVD rental schema. Great for learning about rental systems, inventory management, and customer analytics.
41+
42+
### 3. **[Chinook](https://github.com/lerocha/chinook-database)** - 💾 Digital Media Store
43+
44+
```bash
45+
git clone https://github.com/lerocha/chinook-database
46+
```
47+
48+
A digital media store database with artists, albums, tracks, and customers. Excellent for practicing complex joins and music industry queries.
49+
50+
Each database comes with a complete schema plus realistic data you can load directly into PostgreSQL. Between the three, you'll have customers, invoices, movies, music, orders, and more — plenty of tables to slice and dice.
51+
52+
---
53+
54+
## 🛝 Setting Up the Playground
55+
56+
Here's the step-by-step process I use:
57+
58+
### Step 1: Clone the Repository
59+
60+
```bash
61+
git clone https://github.com/pthom/northwind_psql
62+
cd northwind_psql
63+
```
64+
65+
### Step 2: Create a Database
66+
67+
Connect to PostgreSQL and create a new database:
68+
69+
```bash
70+
psql -U postgres
71+
```
72+
73+
Inside psql:
74+
75+
```sql
76+
CREATE DATABASE northwind;
77+
\q
78+
```
79+
80+
### Step 3: Load the Schema and Data
81+
82+
From your terminal (not inside psql):
83+
84+
```bash
85+
psql -U postgres -d northwind -f northwind.sql
86+
```
87+
88+
That's it! The Northwind database is now live in your PostgreSQL instance.
89+
90+
### Step 4: Repeat for Other Databases
91+
92+
You can follow the same process for Pagila or Chinook, just swap the repository URLs and database names:
93+
94+
- For Pagila: `CREATE DATABASE pagila;`, `psql -U postgres -d pagila -f pagila-schema.sql` (for the pagila schema configuration) and `psql -U postgres -d pagila -f pagila.sql`
95+
- For Chinook: `CREATE DATABASE chinook;` and `psql -U postgres -d chinook -f Chinook_PostgreSQL.sql`
96+
97+
---
98+
99+
## 📈 Why This Beats CSVs
100+
101+
Sure, you can grab a random CSV off Kaggle or mock up some rows yourself — but you miss out on **relationships**. These sample databases are full of foreign keys, joins, and normalized structures. They force you to think in _queries_, not spreadsheets.
102+
103+
### What Makes These Databases Special
104+
105+
- **Realistic Relationships**: Foreign keys, constraints, and proper normalization
106+
- **Diverse Data Types**: Dates, currencies, text, numbers, and more
107+
- **Business Logic**: These aren't just random data — they represent real business scenarios
108+
- **Query Complexity**: Perfect for practicing everything from simple SELECTs to complex analytical queries
109+
110+
Want to practice grouping revenue by product category, joining customers to orders to regions, or analyzing customer lifetime value? These datasets already have that structure baked in.
111+
112+
---
113+
114+
## 💪 Your SQL Gym Routine
115+
116+
Once you've got one (or all three) loaded up, here's a structured approach to build your SQL fluency:
117+
118+
### 🥉 Beginner Level
119+
120+
- **Basic Queries**: Simple `SELECT` statements with `WHERE` clauses
121+
- **Joins**: Start with `INNER JOIN`, then move to `LEFT JOIN` and `RIGHT JOIN`
122+
- **Aggregations**: `GROUP BY`, `COUNT()`, `SUM()`, `AVG()`, `MIN()`, `MAX()`
123+
124+
### 🥈 Intermediate Level
125+
126+
- **Complex Joins**: Multiple table joins and self-joins
127+
- **Subqueries**: Correlated and non-correlated subqueries
128+
- **Window Functions**: `ROW_NUMBER()`, `RANK()`, `LAG()`, `LEAD()`
129+
- **Common Table Expressions (CTEs)**: `WITH` clauses for cleaner, more readable queries
130+
131+
### 🏅 Advanced Level
132+
133+
- **Analytical Queries**: "Top 10 customers by lifetime value"
134+
- **Time Series Analysis**: "Most rented films per month"
135+
- **Complex Reporting**: "Artists with more than 10 albums"
136+
- **Performance Optimization**: Index usage and query execution plans
137+
138+
### Pro Tips
139+
140+
- **Time Yourself**: Can you write a query in 5 minutes without Googling?
141+
- **Experiment**: Try different approaches to solve the same problem
142+
- **Think in Reps**: SQL is like the gym — repetition builds fluency. The more queries you write, the stronger you get.
143+
144+
Think of it like reps at the gym: the more you do, the more natural SQL feels.
145+
146+
---
147+
148+
## 🎁 Wrapping Up
149+
150+
Keeping SQL sharp isn't just about memorizing syntax — it's about staying fluent. Having these databases on hand means you can drop in, write some queries, and build that fluency whenever you've got the itch (or an interview coming up).
151+
152+
### 🪜 Next Steps
153+
154+
1. **Pick one database** and start with the basics
155+
2. **Set a regular practice schedule** — even 15 minutes a day makes a difference
156+
3. **Challenge yourself** with increasingly complex queries
157+
4. **Document your learning** — keep a notebook of interesting queries and techniques
158+
159+
Spin them up once, keep them around, and you'll never have to say "ugh, I don't have a dataset handy" again. Your future self (and your interviewers) will thank you.
160+
161+
---
162+
163+
### 💡 Would you be interested in a follow-up post? I’m thinking either:
164+
165+
1. A set of structured exercises for each of these databases (a “SQL training plan”), or
166+
2. A guide on how to take the same data and visualize it in Plotly for more advanced analysis.
167+
168+
Let me know what would be most useful — I’d love to dig deeper in the next article.

src/pages/blog.astro

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -47,48 +47,6 @@ const allTags = await getAllTags();
4747
</div>
4848
</section>
4949

50-
<!-- Featured Posts -->
51-
<section class="py-12 blog-bg">
52-
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
53-
<h2 class="text-2xl font-bold blog-title mb-8">Featured Posts</h2>
54-
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
55-
{blogPosts.filter(post => post.featured).slice(0, 3).map((post) => (
56-
<article class="featured-post neon-card overflow-hidden hover:shadow-neon-glow transition-all duration-300 flex flex-col">
57-
<div class="h-64 blog-image-bg flex items-center justify-center overflow-hidden">
58-
<Image
59-
src={post.image || "/assets/og-default.png"}
60-
alt={post.title}
61-
width={400}
62-
height={300}
63-
class="w-full h-full object-cover"
64-
loading="lazy"
65-
/>
66-
</div>
67-
<div class="p-6 flex flex-col flex-grow">
68-
<div class="flex items-center text-sm blog-meta mb-3">
69-
<span>{new Date(post.date).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })}</span>
70-
<span class="mx-2">•</span>
71-
<span>{post.readTime} min read</span>
72-
<span class="mx-2">•</span>
73-
<span class="text-yellow-500 font-medium">Featured</span>
74-
</div>
75-
<h3 class="text-xl font-semibold blog-post-title mb-3">{post.title}</h3>
76-
<p class="blog-post-description mb-4">{post.description}</p>
77-
<div class="flex flex-wrap gap-2 mb-4">
78-
{post.tags.slice(0, 3).map((tag) => (
79-
<span class="px-2 py-1 blog-tag text-xs rounded">{tag}</span>
80-
))}
81-
</div>
82-
<a href={`/blog/${post.slug}`} class="blog-link mt-auto">
83-
Read More →
84-
</a>
85-
</div>
86-
</article>
87-
))}
88-
</div>
89-
</div>
90-
</section>
91-
9250
<!-- All Posts -->
9351
<section class="py-20 section-bg">
9452
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">

src/pages/blog/[slug].astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ const blogPost = allBlogPosts.find((p: any) => p.slug === post.slug);
7676
<img
7777
src={post.data.image}
7878
alt={post.data.title}
79-
class="w-full h-96 object-cover rounded-lg shadow-lg article-image"
79+
class="w-full h-full object-cover rounded-lg shadow-lg article-image"
8080
/>
8181
</div>
8282
)}

0 commit comments

Comments
 (0)