Module 1: SQL Foundations35 min

SELECT and FROM Basics

Progress Tracking

Log in to save this lesson and continue from where you left off.

Log in

Being Specific About What You Want

In the last lesson, you learned that SELECT tells the database which columns to return. Simple enough. But there's more nuance here than you might expect, and getting it right matters for both performance and readability.

Why SELECT * is a Bad Habit

When you're exploring a new table, SELECT * is fine. It shows you everything, which helps you understand what you're working with.

SQL
SELECT * FROM techcorp_workforce;

But in real work — queries that run in dashboards, reports, or production systems — SELECT * causes problems:

  • Performance — you're pulling data you don't need. On big tables, this slows everything down.
  • Clarity — someone reading your query can't tell what data actually matters.
  • Fragility — if someone adds a column to the table, your query's output changes unexpectedly.

Get in the habit of specifying columns:

SQL
-- Instead of SELECT *, specify what you need:
SELECT
  id,
  first_name,
  last_name,
  department
FROM techcorp_workforce;

Choosing Column Order

SQL
SELECT
  order_details,
  cust_id,
  total_order_cost
FROM orders;
Table: techcorp_workforce
idfirst_namelast_namedepartmentsalaryphone_numberjoining_date
1SarahMitchellHR95000555-01012021-03-15
2MichaelChenHR88000555-01022022-06-01
3EmilyRodriguezHR825002021-09-20
4DavidParkHR80000555-01042023-01-10
5LisaThompsonHR650002021-04-05
1
Reorder Employee Columns

Select department, first name, and salary from `techcorp_workforce` — in that order.

Tables: techcorp_workforce

This seems trivial, but it matters when you're building reports or exporting data. Put the most important columns first.

Renaming Columns with Aliases

Database column names like employee_id or created_at make sense for developers. They're consistent, predictable, and avoid spaces or special characters. But when you're building a report or dashboard for stakeholders, you want something more readable.

That's what aliases are for. Use AS to rename a column in your output:

2
Try Column Aliases

Rewrite the query using AS to give salary the alias `annual_pay` and department the alias `dept`.

Tables: techcorp_workforce
Quoting Aliases with Spaces

Use double quotes around aliases that contain spaces or special characters. Single-word aliases don't need quotes: joining_date AS start_date works fine.

When Aliases Are Required

Aliases aren't just cosmetic. Sometimes you need them. When you create a calculated column, it has no name until you give it one.

3
Name a Calculated Column

Add a monthly salary column by dividing each employee's annual salary by 12 and giving it a clear label.

Tables: techcorp_workforce

Basic Arithmetic in SELECT

SQL supports standard math operators directly in your SELECT clause:

  • + addition — example: salary + 5000 adds a bonus
  • - subtraction — example: salary - tax calculates net pay
  • * multiplication — example: price * quantity gets a total
  • / division — example: salary / 12 converts annual to monthly
4
Calculate a Salary Bonus

We added a calculated column showing each employee's 10% bonus, now you add a fourth column showing their total salary including that bonus.

Tables: techcorp_workforce
Calculated Columns Don't Change Your Data

Calculated columns only exist in your query results — they don't modify anything stored in the table.

Watch Out for Integer Division

If salary is stored as an integer, salary / 12 may truncate decimals. For precise results in PostgreSQL, cast first: salary::numeric / 12.

Combining Text with Concatenation

Sometimes you need to combine text from multiple columns — for example, creating a full name from first_name and last_name.

String Concatenation

SQL
SELECT
  CONCAT(first_name, ' ', last_name) AS full_name
FROM employees;
5
Build Full Names

Select full name (first and last with a space) and department from `techcorp_workforce`.

Tables: techcorp_workforce
The || operator

PostgreSQL and Oracle also support || for concatenation (first_name || ' ' || last_name). CONCAT() is more portable across dialects.

The AS Keyword is Optional (But Use It Anyway)

SQL lets you skip the AS keyword:

SQL
SELECT
  first_name "First Name"
FROM techcorp_workforce;

This works, but it's harder to read. The explicit AS makes your intent clear. Don't skip it.

Removing Duplicates with DISTINCT

Sometimes you want to know what values exist in a column, not see every row. SELECT DISTINCT removes duplicate values from your results.

Let's look at the orders table:

Table: orders
idcust_idorder_dateorder_detailstotal_order_cost
132019-03-04Coat100
232019-03-01Shoes80
332019-03-07Skirt30
472019-02-01Coat25
572019-03-10Shoes80

Without DISTINCT, you'd see duplicate order details:

6
Run a Basic SELECT

Select just the `order_details` column from the `orders` table.

Tables: orders
7
Get Unique Order Details

Update the query to return only unique order details with SELECT DISTINCT.

Tables: orders

DISTINCT with Multiple Columns

When you use DISTINCT with multiple columns, it removes rows where the entire combination is duplicated:

8
Try Multi-Column DISTINCT

Select the unique combinations of `customer_id` and `order_details` from `orders`.

Tables: orders

This returns unique customer-product pairs. So if customer 3 ordered Shoes twice, you'd only see that combination once.

DISTINCT Applies to the Entire Row

DISTINCT applies to the entire row, not just the first column. This trips people up sometimes.

A Quick Note on Data Types

Every column in a database has a data type. You don't need to memorize these, but it helps to know the main categories:

  • TextVARCHAR, TEXT, CHAR — used for names, emails, descriptions
  • NumbersINTEGER, DECIMAL, FLOAT — used for counts, amounts, percentages
  • DatesDATE, TIMESTAMP, DATETIME — used for when things happened
  • BooleanTRUE/FALSE — used for yes/no flags

Why does this matter? Because you can't do math on text, and you can't search for patterns in numbers (well, you can, but you shouldn't). Understanding data types helps you avoid weird errors and choose the right functions.

We'll cover type-specific operations in later modules. For now, just know that the database handles different data types differently.

Practice: Selecting Columns with Aliases

Let's practice with the restaurant inspections data:

Table: los_angeles_restaurant_health_inspections
serial_numberactivity_datefacility_namescoregradeservice_codeservice_descriptionemployee_idfacility_addressfacility_cityfacility_idfacility_statefacility_zipowner_idowner_namepe_descriptionprogram_element_peprogram_nameprogram_statusrecord_id
DAQHRSETQ2017-06-08MARGARITAS CAFE93A1ROUTINE INSPECTIONEE00000065026 S CRENSHAW BLVDLOS ANGELESFA0023656CA90043OW0004133BAZAN, ASCENCIONRESTAURANT (61-150) SEATS HIGH RISK1638MARGARITAS CAFEACTIVEPR0011718
DA2GQRJOS2017-03-07LAS MOLENDERAS97A1ROUTINE INSPECTIONEE00009972635 WHITTIER BLVDLOS ANGELESFA0160416CA90023OW0125379MARISOL FEREGRINORESTAURANT (0-30) SEATS HIGH RISK1632LAS MOLENDERASINACTIVEPR0148504
DAMQTA46T2016-03-22SANDRA'S TAMALES93A1ROUTINE INSPECTIONEE00010495390 WHITTIER BLVDLOS ANGELESFA0171769CA90022-4032OW0178828SANDRA'S TAMALES INC.RESTAURANT (0-30) SEATS MODERATE RISK1631SANDRA'S TAMALESACTIVEPR0164225
DAXMBTIRZ2018-02-12CAFE GRATITUDE97A1ROUTINE INSPECTIONEE0000828639 N LARCHMONT BLVD STE #102LOS ANGELESFA0058921CA90004OW0005704CAFE GRATITUDE LARCHMONT LLCRESTAURANT (61-150) SEATS HIGH RISK1638CAFE GRATITUDEACTIVEPR0019854
DAK8TBMS02015-09-10THE WAFFLE90A1ROUTINE INSPECTIONEE00007096255 W SUNSET BLVD STE #105LOS ANGELESFA0051830CA90028OW0035796THE WAFFLE, LLCRESTAURANT (61-150) SEATS HIGH RISK1638THE WAFFLEACTIVEPR0010922
9
Select Facility Info with Readable Labels

Find the facility name, owner name, and inspection score. Label the score column as `Inspection Score`.

Tables: los_angeles_restaurant_health_inspections

Common Mistakes

Forgetting the comma between columns

SQL
-- This will give an error:
SELECT
  first_name
  last_name
FROM techcorp_workforce;
-- SQL thinks you're aliasing first_name as "last_name"

-- What you meant:
SELECT
  first_name,
  last_name
FROM techcorp_workforce;

Trailing comma after the last column

SQL
-- This will give an error:
SELECT
  first_name,
  last_name, -- extra comma
FROM techcorp_workforce;

-- Correct:
SELECT
  first_name,
  last_name
FROM techcorp_workforce;

Misspelling column names

SQL won't guess what you meant. If the column is first_name and you type firstname, you'll get an error. Check your spelling, and remember that most databases are case-sensitive for column names.

Key Takeaways

  • Specify columns instead of using SELECT * in production queries.
  • Column order in SELECT determines output order.
  • Use AS to create readable column aliases — always write it explicitly.
  • DISTINCT removes duplicate rows from results — it applies to the entire row, not just the first column.
  • Data types determine what operations you can perform on columns.

What's Next

Now you know how to get data out of a table. But so far, you're getting all rows. In the next lesson, you'll learn to filter data with WHERE — which is when SQL starts to feel actually powerful.