Introduction
Writing SQL queries is the core skill every backend, full-stack, or data engineer must learn. SQL Server may look complicated initially, but once you understand a few foundational queries like:
you can query almost any business database.
This article takes a practical approach. The examples are based on a real-world automotive service management system, similar to the database from Article 1. Every query comes with:
This is written for beginners but structured in a way that builds real production readiness.
Real-World Context
Our database has three tables:
Customer
CREATE TABLE Customer (
CustomerId INT PRIMARY KEY,
FullName NVARCHAR(100),
City NVARCHAR(100)
);
Car
CREATE TABLE Car (
CarId INT PRIMARY KEY,
CustomerId INT,
Brand NVARCHAR(50),
Model NVARCHAR(50),
FOREIGN KEY (CustomerId) REFERENCES Customer(CustomerId)
);
ServiceRecord
CREATE TABLE ServiceRecord (
ServiceId INT PRIMARY KEY,
CarId INT,
ServiceDate DATE,
Cost DECIMAL(10,2),
FOREIGN KEY (CarId) REFERENCES Car(CarId)
);
We will write SQL queries based on this data model.
SELECT: Retrieving Data
The SELECT command is used to fetch data from a table.
Example: Get all customers.
SELECT * FROM Customer;
While SELECT * is useful during development, in production always use explicit columns.
SELECT CustomerId, FullName, City FROM Customer;
WHERE: Filtering Records
Example: Customers from Mumbai.
SELECT FullName, City
FROM Customer
WHERE City = 'Mumbai';
You can use comparison operators:
Example: Find customers whose name starts with "P".
SELECT FullName
FROM Customer
WHERE FullName LIKE 'P%';
ORDER BY: Sorting Results
Sort customer list alphabetically.
SELECT FullName, City
FROM Customer
ORDER BY FullName ASC;
Sort by most recent service first:
SELECT CarId, ServiceDate, Cost
FROM ServiceRecord
ORDER BY ServiceDate DESC;
JOIN: Combining Data from Multiple Tables
JOINs allow you to read related data across tables.
INNER JOIN
Get all cars with customer names.
SELECT
Customer.FullName,
Car.Brand,
Car.Model
FROM Car
INNER JOIN Customer
ON Customer.CustomerId = Car.CustomerId;
LEFT JOIN
Get all customers even if they do not own a car.
SELECT
Customer.FullName,
Car.Brand,
Car.Model
FROM Customer
LEFT JOIN Car
ON Customer.CustomerId = Car.CustomerId;
RIGHT JOIN (Rarely Used)
SELECT *
FROM Customer
RIGHT JOIN Car
ON Customer.CustomerId = Car.CustomerId;
GROUP BY: Summarizing Data
GROUP BY is used with aggregate functions like COUNT, SUM, AVG.
Example: Count how many cars each customer owns.
SELECT
Customer.FullName,
COUNT(Car.CarId) AS TotalCars
FROM Customer
LEFT JOIN Car
ON Customer.CustomerId = Car.CustomerId
GROUP BY Customer.FullName;
Example: Total service cost per car.
SELECT
Car.Brand,
Car.Model,
SUM(ServiceRecord.Cost) AS TotalServiceCost
FROM Car
INNER JOIN ServiceRecord
ON Car.CarId = ServiceRecord.CarId
GROUP BY Car.Brand, Car.Model;
HAVING: Filtering Group Results
Unlike WHERE, HAVING works after grouping.
Example: Customers who own more than one car.
SELECT
Customer.FullName,
COUNT(Car.CarId) AS CarCount
FROM Customer
LEFT JOIN Car
ON Customer.CustomerId = Car.CustomerId
GROUP BY Customer.FullName
HAVING COUNT(Car.CarId) > 1;
TOP: Limit Results
Example: Get the most expensive service.
SELECT TOP 1 *
FROM ServiceRecord
ORDER BY Cost DESC;
DISTINCT: Remove Duplicates
Example: List all unique cities.
SELECT DISTINCT City
FROM Customer;
Combining Multiple Clauses
Example:
Get top 5 customers with the highest total service spending.
SELECT TOP 5
Customer.FullName,
SUM(ServiceRecord.Cost) AS TotalSpent
FROM Customer
JOIN Car ON Customer.CustomerId = Car.CustomerId
JOIN ServiceRecord ON Car.CarId = ServiceRecord.CarId
GROUP BY Customer.FullName
ORDER BY TotalSpent DESC;
This is similar to a real dashboard/report query.
Real-World Case Study
A service company initially exported all service records to Excel and manually calculated revenue. It took nearly 5 hours per week and had frequent mistakes.
After learning GROUP BY queries:
Revenue reports were generated instantly.
Customer trends became visible.
The business started offering targeted service packages.
SQL skills directly improved business outcomes.
Common Beginner Mistakes
| Mistake | Better Practice |
|---|
| Using SELECT * in production | Use explicit column names |
| Forgetting WHERE condition | May return huge datasets |
| Using RIGHT JOIN instead of LEFT JOIN | LEFT JOIN is usually easier and logical |
| Using HAVING for non-aggregates | Use WHERE instead |
| No ORDER BY in reports | Reports appear random |
Best Practices
Always format your SQL for readability.
Use meaningful aliases.
Use LIMIT/TOP when testing.
Follow naming conventions.
Example with formatting
SELECT
c.FullName,
SUM(sr.Cost) AS TotalSpent
FROM Customer c
JOIN Car ca ON c.CustomerId = ca.CustomerId
JOIN ServiceRecord sr ON ca.CarId = sr.CarId
GROUP BY c.FullName
ORDER BY TotalSpent DESC;
Summary
SQL querying begins with understanding and practicing:
SELECT
JOIN
GROUP BY
Filtering and sorting
These building blocks enable beginners to confidently query real business systems and prepare for more advanced topics like indexing, triggers, optimization, and stored procedures.