-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Apply suggestions from Niko's code review
Co-authored-by: Nikolas <[email protected]>
- Loading branch information
1 parent
7202fd7
commit 424f13c
Showing
1 changed file
with
40 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
--- | ||
title: 'What are JOINs?' | ||
metaTitle: "JOINs | Prisma's Data Guide" | ||
metaDescription: 'Discover how JOINs allow developers to combine related data from multiple tables.' | ||
title: 'What are JOINs in SQL?' | ||
metaTitle: "What are JOINs in SQL? | Prisma's Data Guide" | ||
metaDescription: 'Discover how JOINs allow developers to combine related data from multiple tables in SQL databases.' | ||
metaImage: '../../dataguide-images/types/relational/what-are-joins/header-image.png' | ||
authors: ['grishmapatel'] | ||
--- | ||
|
@@ -14,25 +14,27 @@ JOINs allow you to combine related data from multiple tables in relational datab | |
|
||
## How data is structured in relational databases | ||
|
||
Before diving into JOINs, it’s important to understand the fundamentals of relational databases. Relational databases provide a way to structure and organize information. In relational databases, data is structured into tables, with columns (attributes) specifying data types (think strings, integers, etc.) and rows containing records (the values for each of the table’s columns). | ||
Before diving into JOINs, it’s important to understand the fundamentals of relational databases. Relational databases provide a way to structure and organize information. In relational databases, data is structured into _tables_, with _columns_ (attributes) specifying _data types_ (think strings, integers, etc.) and _rows_ containing records (the values for each of the table’s columns). | ||
|
||
Let’s demonstrate this concept with a table holding customer information. In the table below, the columns, or customer attributes, are `name`, `age`, and `email address` and the rows represent each customer’s `name`, `age`, and `email address`. | ||
Let’s demonstrate this concept with a table holding customer information. In the table below, the columns, or customer attributes, are `name`, `age`, and `email address` and the rows represent each customer’s `name`, `age`, and `email_address`. | ||
|
||
| name | age | email address | | ||
| name | age | email_address | | ||
| ------- | --- | ----------------- | | ||
| Jenny | 30 | [email protected] | | ||
| Adrian | 28 | [email protected] | | ||
| Synniva | 25 | [email protected] | | ||
|
||
A relational database has the ability to define relationships, or connections, between different tables using primary and foreign keys. All tables in a relational database have a column known as the _primary key_ which uniquely identifies each row. To see how this works in practice, let’s use our previous example. The primary key for the `customers` table would be a column of unique IDs for each customer, called `customer_id`. In other words, no customer would share the same id as another. | ||
A relational database has the ability to define relationships, or connections, between different tables using _primary_ and _foreign keys_. | ||
|
||
All tables in a relational database have a column known as the _primary key_ which uniquely identifies each row. To see how this works in practice, let’s use our previous example: The primary key for the `customers` table would be a column of unique IDs for each customer, called `customer_id`. In other words, no customer would share the same ID as another. | ||
|
||
![table-properties](../../dataguide-images/types/relational/what-are-joins/table-properties.png) | ||
|
||
A _foreign key_ is used to create a relationship between tables by referencing the primary key of another table. To demonstrate the concept of foreign keys, let’s say we have another table called `orders` with columns: `order_id`, `cost`, and `order_date`. We can link the `orders` table (left table in diagram) with the `customers` table (right table in diagram) by including a `customer_id` column (foreign key), associating each order with the corresponding customer. | ||
|
||
![relationship-between-tables](../../dataguide-images/types/relational/what-are-joins/relationship-between-tables.png) | ||
|
||
## What are JOINs | ||
## What are JOINs? | ||
|
||
A useful feature of relational databases is the concept of _JOINs_, a type of SQL operation that combines relevant data from distinct tables often based on the primary and foreign key. | ||
|
||
|
@@ -53,7 +55,7 @@ Using our example from earlier, when you perform a standard JOIN between the `cu | |
|
||
The result set for the tables would be: | ||
|
||
| customer_id | name | age | email address | order_id | cost | order_date | | ||
| customer_id | name | age | email_address | order_id | cost | order_date | | ||
| ----------- | ------- | --- | ----------------- | -------- | ------- | ---------- | | ||
| 1 | Jenny | 30 | [email protected] | 1 | $150.00 | 4/1/2024 | | ||
| 2 | Adrian | 28 | [email protected] | 2 | $200.00 | 3/29/2024 | | ||
|
@@ -68,21 +70,21 @@ Sometimes you may want to get different rows from each table. There are differen | |
|
||
### Traditional JOINs | ||
|
||
The most common form of JOIN operations you will encounter are `INNER JOIN`, `LEFT JOIN`, `RIGHT JOIN`, `FULL JOIN`, and `CROSS JOIN`. To demonstrate the following types of JOINs, we will use the following `customers` and `orders` (modified) tables: | ||
The most common form of JOIN operations you will encounter are `INNER JOIN`, `LEFT JOIN`, `RIGHT JOIN`, `FULL JOIN`, and `CROSS JOIN`. To demonstrate these JOIN types, we will use the following `customers` and `orders` (modified) tables: | ||
|
||
| customer_id | name | age | email address | | ||
| customer_id | name | age | email_address | | ||
| ----------- | ------- | --- | ----------------- | | ||
| 1 | Jenny | 30 | [email protected] | | ||
| 2 | Adrian | 28 | [email protected] | | ||
| 3 | Synniva | 25 | [email protected] | | ||
|
||
| order_id(primary key) | cost | order_date | customer_id(foreign key) | | ||
| order_id (primary key) | cost | order_date | customer_id (foreign key) | | ||
| --------------------- | ------- | ---------- | ------------------------ | | ||
| 1 | $150.00 | 4/1/2024 | 1 | | ||
| 2 | $200.00 | 3/29/2024 | 2 | | ||
| 3 | $20.00 | 4/2/2024 | 1 | | ||
|
||
#### **INNER JOIN** | ||
#### `INNER JOIN` | ||
|
||
The `INNER JOIN` is the default JOIN and returns rows from both tables only where there is a match. Here is the associated query for the `customers` and `orders` table: | ||
|
||
|
@@ -176,22 +178,14 @@ FULL JOIN orders | |
MySQL does not natively support `FULL JOIN`s. As a workaround, we can use a `LEFT JOIN` combined with an “anti-JOIN,” or a JOIN operation that finds results that are _not_ in common between tables (specified by the NULL). The `UNION ALL` allows us to combine these together. | ||
|
||
```sql | ||
( SELECT | ||
* | ||
FROM | ||
customers | ||
LEFT JOIN orders | ||
ON customers.customer_id = orders.customer_id | ||
) | ||
(SELECT * | ||
FROM customers | ||
LEFT JOIN orders ON customers.customer_id = orders.customer_id) | ||
UNION ALL | ||
( SELECT | ||
* | ||
FROM | ||
customers | ||
RIGHT JOIN orders | ||
ON customers.customer_id = orders.customer_id | ||
WHERE customers.customer_id IS NULL | ||
); | ||
(SELECT * | ||
FROM customers | ||
RIGHT JOIN orders ON customers.customer_id = orders.customer_id | ||
WHERE customers.customer_id IS NULL ); | ||
``` | ||
|
||
Here is the result table after using a `FULL JOIN`: | ||
|
@@ -211,7 +205,7 @@ When depicted as a Venn diagram, a `FULL JOIN` represents both circles. In other | |
|
||
#### **CROSS JOIN** | ||
|
||
A `CROSS JOIN` returns the Cartesian product of the two tables, meaning every row from the first table is combined with every row from the second table. In this syntax, the result is formed by adding each of the rows in the first table with each of the rows from the second table like so: | ||
A `CROSS JOIN` returns the [Cartesian product](https://www.sciencedirect.com/topics/computer-science/cartesian-product) of the two tables, meaning every row from the first table is combined with every row from the second table. In this syntax, the result is formed by adding each of the rows in the first table with each of the rows from the second table like so: | ||
|
||
```sql | ||
t1.r1 + t2.r1 | ||
|
@@ -225,18 +219,20 @@ t1.r3 + t2.r2 | |
t1.r3 + t2.r3 | ||
``` | ||
|
||
> **Note:** In MySQL, the concept of a `CROSS JOIN` is combined with the `INNER JOIN`. Read more in the [data guide](https://www.prisma.io/dataguide/mysql/reading-and-querying-data/joining-tables#different-types-of-joins). | ||
> **Note:** In MySQL, the concept of a `CROSS JOIN` is combined with the `INNER JOIN`. Read more in the [here](https://www.prisma.io/dataguide/mysql/reading-and-querying-data/joining-tables#different-types-of-joins). | ||
|
||
With a `CROSS JOIN`, each row from the `customers` table is combined with each row from the `orders` table, resulting in 9 rows. However, we won’t show the result table as a `CROSS JOIN` wouldn’t accurately pair the customer with their respective orders. | ||
With a `CROSS JOIN`, each row from the `customers` table is combined with each row from the `orders` table, resulting in a total of 9 rows. However, we won’t show the result table as a `CROSS JOIN` wouldn’t accurately pair the customer with their respective orders. | ||
|
||
|
||
To learn more about JOINs in PostgreSQL, read more in the data guide [here](https://www.prisma.io/dataguide/postgresql/reading-and-querying-data/joining-tables). To learn more about JOINs in MySQL, read more in the data guide [here](https://www.prisma.io/dataguide/mysql/reading-and-querying-data/joining-tables). | ||
To learn more about database-specific details of JOIN operations, check out these additional pages in the data guide: | ||
- [JOINs in PostgreSQL](https://www.prisma.io/dataguide/postgresql/reading-and-querying-data/joining-tables) | ||
- [JOINs in MySQL](https://www.prisma.io/dataguide/mysql/reading-and-querying-data/joining-tables) | ||
|
||
|
||
### LATERAL JOINs | ||
|
||
Lateral JOINs offer a different syntax to combining tables compared to traditional JOINs. In a `LATERAL JOIN`, the second table is presented as a subquery, and the JOIN criteria is defined within the WHERE clause of the subquery. | ||
Lateral JOINs offer a different syntax to combining tables compared to traditional JOINs. In a `LATERAL JOIN`, the second table is presented as a _subquery_, and the JOIN criteria is defined within the `WHERE` clause of the subquery. | ||
|
||
According to the [PostgreSQL](https://www.postgresql.org/docs/9.3/sql-select.html#SQL-FROM) docs, “The `LATERAL` key word can precede a sub-`SELECT FROM` item. This allows the sub-`SELECT` to refer to columns of `FROM` items that appear before it in the `FROM` list. (Without `LATERAL`, each sub-`SELECT` is evaluated independently and so cannot cross-reference any other `FROM` item.)” | ||
|
||
|
@@ -247,17 +243,12 @@ In other words, a `LATERAL JOIN` is like a foreach loop, where PostgreSQL iterat | |
Here is the associated query for the `customers` and `orders` table: | ||
|
||
```sql | ||
SELECT | ||
* | ||
FROM | ||
customers | ||
LEFT JOIN LATERAL | ||
(SELECT * | ||
FROM orders | ||
WHERE orders.customer_id = customers.customer_id | ||
) AS alias ON TRUE; | ||
|
||
``` | ||
SELECT * | ||
FROM customers | ||
LEFT JOIN LATERAL | ||
(SELECT * | ||
FROM orders | ||
WHERE orders.customer_id = customers.customer_id ) AS ALIAS ON TRUE; | ||
|
||
Here is the result table after using a `LATERAL JOIN`: | ||
|
||
|
@@ -272,13 +263,13 @@ In this case, the result would be the same as a `LEFT JOIN` and `FULL JOIN`. | |
|
||
<PrismaOutlinks> | ||
|
||
💡 Prisma ORM’s preview JOIN feature works with Postgres and MySQL versions >8. To read more about the preview feature, read the blog post [here](https://www.prisma.io/blog/prisma-orm-now-lets-you-choose-the-best-join-strategy-preview) | ||
💡 Prisma ORM makes it easy to query relations between tables without thinking about the intricacies and low-level complexities of SQL operations. Read the docs to learn more about [relation queries](https://www.prisma.io/docs/orm/prisma-client/queries/relation-queries). | ||
|
||
</PrismaOutlinks> | ||
|
||
## Implementing JOINs for different relations | ||
|
||
It’s important to understand database relations when selecting the appropriate JOIN type. In the context of databases, relations describe a relationship between tables in a database. | ||
It’s important to understand database _relations_ when selecting the appropriate JOIN type. In the context of databases, relations describe a relationship between tables in a database. | ||
|
||
In this section, we will illustrate both the one-to-one and the one-to-many relations along with considerations for selecting the appropriate JOIN type for each. | ||
|
||
|
@@ -383,8 +374,8 @@ Here is an example of what the result set would look like using `LATERAL JOIN`s | |
| id | email | post_titles | | ||
| --- | --------------- | ------------------------------------------------------------------------------------------------------------------------------ | | ||
| 1 | [email protected] | [{"post title": "Introduction to Prisma ORM"}, {"post title": "Introduction to JOINs"}, {"post title": "Introduction to SQL"}] | | ||
| 2 | [email protected] | [{"post title": "Using Prisma Client"}] | | ||
| 1 | [email protected] | `[{"post title": "Introduction to Prisma ORM"}, {"post title": "Introduction to JOINs"}, {"post title": "Introduction to SQL"}]` | | ||
| 2 | [email protected] | `[{"post title": "Using Prisma Client"}]` | | ||
As you can see, `LATERAL JOIN`s combined with JSON aggregation leads to a cleaner result set with no unnecessary duplication. Each of Jenny’s posts got consolidated into a JSON array, transforming three rows from the previous result set into one. | ||
|
@@ -396,6 +387,6 @@ To wrap up, we introduced the concept of JOINs and how they allow us to combine | |
<PrismaOutlinks> | ||
💡 JOINs can be very complicated in real-world applications, especially if you add more conditions to a query, e.g. filtering and pagination. Prisma ORM lets you easily query relations and figures out an effective JOIN query for you under the hood. Learn more about the `relationJoins` Preview feature introduced in version 5.7.0 in the Prisma [documentation](https://www.prisma.io/docs/orm/reference/prisma-client-reference#relationloadstrategy-preview). | ||
💡 JOINs can be very complicated in real-world applications, especially if you add more conditions to a query, e.g. filtering and pagination. Prisma ORM lets you easily query relations and figures out an effective JOIN query for you under the hood. Read the docs to learn more about [relation queries](https://www.prisma.io/docs/orm/prisma-client/queries/relation-queries). | ||
</PrismaOutlinks> |