SQL, queries, and NoSQL databases

~23 min

A database full of well-organized information is useful only if people and applications can retrieve what they need.

A question sent to a database is called a Concept · lights on your mapqueryA question sent to a database, a request to retrieve or change stored information. Engineers use queries to retrieve and change application data; analysts use them to investigate behavior and measure performance; product managers use them to answer questions about customers, features, and business results..

Relational databases are commonly queried using SQL.

What is SQL?

Concept · lights on your mapSQLStructured Query Language, pronounced “sequel” or “S-Q-L.” The language used to query relational databases. Designed to resemble structured English, which is why reading one is far easier than writing one. stands for Structured Query Language.

You will hear it pronounced both “sequel” and “S-Q-L”, and both pronunciations are widely used.

SQL has existed for decades and remains one of the most important languages in software, analytics, finance, operations, and product work.

Engineers use SQL to retrieve and change application data. Analysts use it to investigate behavior and measure performance. Product managers may use it to answer questions about customers, features, and business results.

You do not need to become an expert SQL writer yet because the immediate goal is to reach SQL reading level: the ability to look at a query and understand what question it is asking.

SQL was designed to resemble structured English, so its basic commands are relatively approachable.

Reading a simple query

Consider this query:

A simple querySQL
1SELECT name, email
SELECT identifies the columns the query should return.
2FROM customers;
FROM identifies the table containing those columns. The semicolon marks the end of the SQL statement.

You can read it as:

Give me the name and email columns from the customers table.

The result might resemble:

nameemail
Erik Smitherik@post.com
Daniel Kimdaniel@example.com

SQL does not normally return the entire table automatically. The query describes which information should be included in the result.

Selecting every column

An asterisk means “all columns”:

Selecting every columnSQL
1SELECT *
2FROM orders;

This can be read as:

Give me every column from every row in the orders table.

The asterisk is convenient when exploring a table, but production applications often request only the columns they need because retrieving unnecessary data can consume more processing, memory, and network capacity. Less data, less work.

Filtering rows with WHERE

Suppose the orders table stores money as cents:

order_idcustomer_idtotal_centsstatus
1042881450confirmed
1043892400preparing
1044883100confirmed

This query retrieves orders worth more than $20:

Filtering rowsSQL
1SELECT *
2FROM orders
3WHERE total_cents > 2000;
WHERE filters the rows: Module 3’s conditionals, applied to stored data.

You can read it as:

Give me every column from every row in orders whose total is greater than 2,000 cents.

WHERE filters the rows.

This connects directly to Module 3’s conditionals, since the database examines each relevant row and includes only those for which the condition is true.

Other conditions might look like:

  • WHERE status = 'confirmed'
  • WHERE customer_id = 88
  • WHERE total_cents >= 1000

Text values are commonly surrounded by single quotation marks.

Combining conditions

SQL can combine several conditions.

For example:

Requiring both conditionsSQL
1SELECT *
2FROM orders
3WHERE status = 'confirmed'
4AND total_cents > 2000;

This asks for orders that are both confirmed and worth more than $20.

A query could also use OR:

Allowing either conditionSQL
1SELECT *
2FROM orders
3WHERE status = 'confirmed'
4OR status = 'preparing';

This asks for orders in either of those two states.

The connection to programming logic is direct:

  • WHERE introduces a condition.
  • AND requires both conditions.
  • OR allows either condition.

The problem of information across tables

The relational model deliberately separates related facts into different tables.

The customers table might contain:

customer_idnameemail
88Erik Smitherik@post.com
89Daniel Kimdaniel@example.com

The orders table might contain:

order_idcustomer_idtotal_centsstatus
1042881450confirmed
1043892400preparing
1044883100confirmed

The order rows contain customer IDs, but they do not repeat the customers’ email addresses.

What if we want a result containing both the order total and the customer’s email?

But the information lives in two different tables.

SQL solves this using a JOIN.

Reading a JOIN

Consider this query:

A JOIN across two tablesSQL
1SELECT customers.email, orders.total_cents
2FROM orders
3JOIN customers
4ON orders.customer_id = customers.customer_id
5WHERE orders.status = 'confirmed';

Read it one section at a time.

SELECT customers.email, orders.total_cents asks for the customer’s email and the order’s total.

FROM orders starts from the orders table.

JOIN customers connects matching information from the customers table.

ON orders.customer_id = customers.customer_id matches an order’s foreign key to the customer’s primary key.

WHERE orders.status = 'confirmed' keeps only confirmed orders.

Together, the query means:

Give me the customer email and total for every confirmed order.

The result might be:

emailtotal_cents
erik@post.com1450
erik@post.com3100

You have now read one of the central operations in relational databases.

How a JOIN follows relationships

In the previous lesson, you learned that orders.customer_id refers to customers.customer_id.

The JOIN follows that relationship.

For order 1042, the database sees orders.customer_id = 88, then finds the customer row where customers.customer_id = 88 and combines information from the matching rows into the query result.

This does not permanently merge the tables, but creates a result for this particular question.

The type of JOIN matters

The plain JOIN in the example commonly means an inner join.

An inner join returns only rows that have a match on both sides, so if an order referred to no matching customer, that order would not appear in the result. No match, no row.

Other join types can preserve unmatched rows from one or both tables. You may later encounter names such as:

  • LEFT JOIN
  • RIGHT JOIN
  • FULL JOIN

You do not need to master them yet.

For now, remember:

A JOIN combines related rows from multiple tables according to a matching condition.

Using shorter table names

SQL queries sometimes give tables temporary shorter names called aliases.

The previous query could be written as:

The same JOIN, with aliasesSQL
1SELECT c.email, o.total_cents
2FROM orders AS o
3JOIN customers AS c
4ON o.customer_id = c.customer_id
5WHERE o.status = 'confirmed';

Here, o refers to orders and c refers to customers, and once you understand what each letter stands for, aliases can make long queries easier to read.

Queries that summarize data

SQL can also calculate summaries.

Suppose you want to know how many confirmed orders exist:

Counting rowsSQL
1SELECT COUNT(*)
2FROM orders
3WHERE status = 'confirmed';

COUNT(*) counts the matching rows.

To calculate the total value of confirmed orders:

Adding valuesSQL
1SELECT SUM(total_cents)
2FROM orders
3WHERE status = 'confirmed';

SUM adds the matching values.

Other common operations include:

  • AVG for an average
  • MIN for the smallest value
  • MAX for the largest value

These operations are one reason SQL is important beyond application engineering. The same stored data can support analytics, reporting, finance, and product decisions.

Reads versus writes

Database operations are often divided into reads and writes.

A Concept · lights on your mapreadAn operation that retrieves existing information without intentionally changing it. SELECT is the primary one. Reads observe state; writes create it, which is why reads are cheaper to scale. retrieves existing information without intentionally changing it.

SELECT is the primary SQL command used for reads:

A readSQL
1SELECT *
2FROM orders
3WHERE order_id = 1042;

A Concept · lights on your mapwriteAn operation that changes the database’s stored state: INSERT adds a row, UPDATE changes one, DELETE removes one. Unlike a read, it creates new authoritative truth, which is why it needs more coordination and care. changes the database’s stored state.

Common write commands include:

  • INSERT
  • UPDATE
  • DELETE

These commands correspond roughly to creating, modifying, and removing records.

INSERT

INSERT adds a new row.

For example:

Creating a new order rowSQL
1INSERT INTO orders (
2order_id,
3customer_id,
4total_cents,
5status
6)
7VALUES (
81045,
988,
101750,
11'confirmed'
12);

This asks the database to create a new order row.

Before accepting the write, the database may check:

  • Whether the ID is unique
  • Whether customer 88 exists
  • Whether required values are present
  • Whether each value matches the column’s data type
  • Whether other constraints are satisfied

UPDATE

UPDATE changes existing rows.

For example:

Changing one orderSQL
1UPDATE orders
2SET status = 'preparing'
3WHERE order_id = 1045;

This means:

Find order 1045 and change its status to preparing.

The WHERE clause is especially important because without an appropriate filter, an update could affect every row in the table.

For example:

An update with no filterSQL
1UPDATE orders
2SET status = 'preparing';
No WHERE clause, so this would attempt to change every order.

would attempt to change the status of all orders.

This is one reason writes require care.

DELETE

DELETE removes rows:

Removing a rowSQL
1DELETE FROM orders
2WHERE order_id = 1045;

This asks the database to remove order 1045, though many products do not permanently delete important business records immediately.

An application may instead update a status:

Cancelling instead of deletingSQL
1UPDATE orders
2SET status = 'cancelled'
3WHERE order_id = 1045;

This preserves the historical record while indicating that the order is no longer active, and the product’s business and legal requirements help determine which approach is appropriate.

Why writes require coordination

Reads and writes have different consequences because a read observes stored information while a write changes the source of truth.

That means writes often require the system to coordinate questions such as:

  • Is the new data valid?
  • Is another write happening simultaneously?
  • Should this operation be allowed?
  • What happens if part of it fails?
  • Which caches or copies must be updated?
  • Should an audit history be preserved?

This does not mean that every write is slower than every read. A simple write may be faster than a complicated analytical query.

The deeper distinction is:

Reads observe state. Writes create new authoritative state.

Because writes change the truth, errors can have lasting consequences.

Can reads be cached?

Reads are often easier to cache because they do not intentionally change the database.

For example, a public list of popular drinks might be stored in an application cache rather than recalculated for every request.

However, not every read can be cached safely.

A cached result may be inappropriate when:

  • The data changes frequently
  • The user needs the newest value
  • The response contains private information
  • Different users have different permissions
  • A recent write must appear immediately
  • The query depends on rapidly changing state

A bank balance cannot always be treated like a public menu.

Caching remains a tradeoff between speed and freshness, governed by the needs of the product.

Read-heavy and write-heavy systems

Many consumer applications perform more reads than writes. A user might view a product page many times before placing one order, and thousands of people may read a public post that was written once.

This can lead to a read-heavy workload.

Other systems may be write-heavy. Sensors, analytics pipelines, financial markets, and logging systems can generate enormous numbers of new records.

The balance between reads and writes affects architectural choices such as:

  • Caching
  • Database replicas
  • Indexes
  • Data partitioning
  • Queueing
  • Storage design

You will encounter these concepts in later modules.

For now, recognize that teams make these choices by studying their actual traffic patterns rather than assuming every product behaves the same way.

What is NoSQL?

Relational databases are not the only type of database.

Concept · lights on your mapNoSQL databaseA broad category covering databases that do not rely exclusively on the traditional relational table model; the name is often interpreted as “not only SQL.” It includes several different models: document, key-value, wide-column, and graph databases. The best-known kind is the document database, which stores JSON-like documents; MongoDB is a widely recognized example. is a broad category covering databases that do not rely exclusively on the traditional relational table model.

The name is often interpreted as:

“Not only SQL”

rather than literally “no SQL.”

NoSQL includes several different database models, such as:

  • Document databases
  • Key-value databases
  • Wide-column databases
  • Graph databases

These categories organize and retrieve data in different ways, and they should not be treated as one single design.

Document databases

One well-known type of NoSQL database is the document database, which stores records as document-like structures, often resembling JSON. The most widely recognized document database is MongoDB.

An order might be stored as:

An order as one documentJSON
1{
2"order_id": 1042,
3"customer": {
4"customer_id": 88,
5"name": "Erik Smith"
6},
7"items": [
The order and its items live together in one nested document.
8{
9"product_id": 21,
10"name": "Latte",
11"quantity": 2
12},
13{
14"product_id": 22,
15"name": "Croissant",
16"quantity": 1
17}
18],
19"total_cents": 1450,
20"status": "confirmed"
21}

The order and its items can be stored together in one nested document, which differs from the relational approach, where the information might be separated across orders, order_items, customers, and products tables. Everything travels together.

Flexible does not mean structureless

Document databases are often described as schema-flexible, meaning two documents in the same collection may contain somewhat different fields.

For example, one customer document might contain:

One customer documentJSON
1{
2"customer_id": 88,
3"name": "Erik Smith",
4"preferred_store": 12
5}

while another contains:

Another, with different fieldsJSON
1{
2"customer_id": 89,
3"name": "Daniel Kim",
4"loyalty_tier": "gold"
5}

This flexibility can make it easier to evolve data shapes.

However, document databases are not automatically structureless. Applications still expect particular fields and types, and many document databases support schema validation.

Without discipline, flexible records can become inconsistent and difficult to understand. The absence of a rigid relational schema does not eliminate the need for a data model.

Relational versus document design

A relational database emphasizes:

  • Tables
  • Relationships
  • Constraints
  • Joins
  • Consistent schemas

A document database emphasizes:

  • Self-contained documents
  • Nested structures
  • Flexible fields
  • Retrieving related information together

Neither model is automatically superior.

A relational database may be a strong choice when:

  • Relationships between entities are important
  • Consistency rules must be enforced
  • Data needs to be queried in many combinations
  • Transactions connect several records
  • The structure is reasonably well understood

A document database may be useful when:

  • Data naturally forms self-contained documents
  • Related information is usually retrieved together
  • Records have varying shapes
  • The structure changes frequently
  • The application benefits from nested data

The correct decision depends on the product’s needs and access patterns.

Relational databases can store JSON too

The boundary is not absolute.

Modern relational databases such as PostgreSQL can store JSON documents inside columns, while document databases can enforce validation and model relationships.

Database systems increasingly borrow ideas from one another.

The choice is therefore rarely:

Perfectly rigid tables or completely unstructured blobs.

Instead, teams ask:

  • What relationships exist?
  • Which rules must be enforced?
  • How will the data be queried?
  • Which information changes together?
  • How consistent must the data remain?
  • How quickly will the model evolve?
  • What expertise does the team have?

These are data-modeling and system-design questions, not debates with one universal winner.

Postgres or MongoDB?

When engineers discuss:

“Postgres or MongoDB?”

they may be comparing:

  • Relational tables versus documents
  • Joins versus nested data
  • Strong relational constraints versus schema flexibility
  • Different querying and scaling patterns
  • Existing team knowledge and infrastructure

The actual decision is usually more nuanced than “strict versus flexible,” but those are part of the tradeoff.

Seeing the complete data flow

Imagine that the frontend sends an authenticated request to retrieve Erik’s confirmed orders.

The backend might execute:

The backend’s querySQL
1SELECT
2orders.order_id,
3orders.total_cents,
4customers.email
5FROM orders
6JOIN customers
7ON orders.customer_id = customers.customer_id
8WHERE orders.customer_id = 88
9AND orders.status = 'confirmed';

The database follows the relationship between the tables, filters the relevant rows, and returns the requested fields.

The backend then serializes the result into JSON:

The API responseJSON
1{
2"orders": [
3{
4"order_id": 1042,
5"total_cents": 1450,
6"customer_email": "erik@post.com"
7},
8{
9"order_id": 1044,
10"total_cents": 3100,
11"customer_email": "erik@post.com"
12}
13]
14}

The database speaks in tables and query results, while the API commonly sends the result as JSON.

SQL and JSON play different roles in the same flow.

The mental model to remember

A query is a request for a database to retrieve or change information.

SQL is the language commonly used to work with relational databases.

SELECT chooses columns.

FROM identifies a table.

WHERE filters rows.

A JOIN combines related rows from multiple tables using a matching condition.

INSERT, UPDATE, and DELETE change stored data.

A read observes existing state. A write changes authoritative state.

Reads can sometimes be cached, but only when the product can tolerate the corresponding freshness, privacy, and permission tradeoffs.

NoSQL is an umbrella category covering several non-relational database models.

A document database stores document-like structures that often resemble JSON.

MongoDB is a widely used document database.

You should now be able to read a simple SQL query, follow a join between primary and foreign keys, and understand the basic tradeoff between relational tables and document-oriented storage.

Check — then the lesson continues

Read this query like an engineer: SELECT customers.email FROM customers JOIN orders ON orders.customer_id = customers.customer_id WHERE orders.total_cents > 10000; Who's getting an email?

▼ answer the check to continue ▼