@@ -128,3 +128,237 @@ a time.
128128 erDiagram
129129 employee }o--|{ employee_role : execute
130130 role }o--|{ employee_role : assign
131+
132+ Joining data
133+ ============
134+
135+ ``JOIN`` is used to *join* data fetched from multiple related tables.
136+ To build a valid query you are to set the tables to join and parameter to use
137+ for this operation.
138+
139+ Common syntax is:
140+
141+ ::
142+
143+ T1 join_type T2 [ join_condition ]
144+
145+ There are various join types available.
146+ Here are is some dummy data to demonstrate their purpose.
147+
148+ .. table:: poem
149+
150+ +----+------------------------+-----------+
151+ | id | title | author_id |
152+ +====+========================+===========+
153+ | 1 | On the Field of Battle | 1 |
154+ +----+------------------------+-----------+
155+ | 2 | Moses | 2 |
156+ +----+------------------------+-----------+
157+ | 3 | The Forest Song | 1 |
158+ +----+------------------------+-----------+
159+ | 4 | In the Catacombs | null |
160+ +----+------------------------+-----------+
161+ | 5 | The Singing Stones | 1 |
162+ +----+------------------------+-----------+
163+ | 6 | Ancient Fairy Tales | null |
164+ +----+------------------------+-----------+
165+ | 7 | My Thoughts | 2 |
166+ +----+------------------------+-----------+
167+ | 8 | To Shevchenko | null |
168+ +----+------------------------+-----------+
169+
170+
171+ .. table:: author
172+
173+ +----+---------------+
174+ | id | name |
175+ +====+===============+
176+ | 1 | Larysa Kosach |
177+ +----+---------------+
178+ | 2 | Ivan Franko |
179+ +----+---------------+
180+ | 3 | John Doe |
181+ +----+---------------+
182+
183+ .. code-block:: sql
184+
185+ CREATE TABLE author
186+ (
187+ id SERIAL PRIMARY KEY,
188+ name VARCHAR(32) NOT NULL UNIQUE
189+ );
190+ CREATE TABLE poem
191+ (
192+ id SERIAL PRIMARY KEY,
193+ title VARCHAR(32) NOT NULL UNIQUE,
194+ author_id INT REFERENCES author (id)
195+ );
196+ INSERT INTO author(name)
197+ VALUES ('Larysa Kosach'),
198+ ('Ivan Franko'),
199+ ('John Doe');
200+ INSERT INTO poem(title, author_id)
201+ VALUES ('On the Field of Battle', 1),
202+ ('Moses', 2),
203+ ('The Forest Song', 1),
204+ ('In the Catacombs', null),
205+ ('The Singing Stones', 1),
206+ ('Ancient Fairy Tales', null),
207+ ('My Thoughts', 2),
208+ ('To Shevchenko', null)
209+ ;
210+
211+ Join types
212+ ----------
213+
214+ :Cross join:
215+
216+ .. code-block::
217+
218+ T1 CROSS JOIN T2
219+
220+ For every possible combination of rows from T1 and T2
221+ (i.e., a Cartesian product), the joined table will contain a row consisting
222+ of all columns in T1 followed by all columns in T2. If the tables have N
223+ and M rows respectively, the joined table will have N * M rows.
224+
225+ :Qualified joins:
226+
227+ .. code-block::
228+
229+ T1 { [INNER] | { LEFT | RIGHT | FULL } [OUTER] } JOIN T2 ON condition
230+
231+ The words ``INNER`` and ``OUTER`` are optional for all forms.
232+ ``INNER`` is the default; ``LEFT``, ``RIGHT`` and ``FULL`` imply ``OUTER``
233+ join.
234+
235+ INNER JOIN
236+ ----------
237+
238+ For each row R1 of T1, the joined table has a row for each row in T2 that
239+ satisfies the join condition with R1.
240+
241+ .. code-block:: sql
242+ :caption: Inner join
243+
244+ SELECT p.title, a.name
245+ FROM poem p
246+ JOIN author a on p.author_id = a.id;
247+
248+ +------------------------+---------------+
249+ | title | name |
250+ +========================+===============+
251+ | On the Field of Battle | Larysa Kosach |
252+ +------------------------+---------------+
253+ | Moses | Ivan Franko |
254+ +------------------------+---------------+
255+ | The Forest Song | Larysa Kosach |
256+ +------------------------+---------------+
257+ | The Singing Stones | Larysa Kosach |
258+ +------------------------+---------------+
259+ | My Thoughts | Ivan Franko |
260+ +------------------------+---------------+
261+
262+ LEFT OUTER JOIN
263+ ---------------
264+
265+ First, an inner join is performed. Then, for each row in T1 that does not
266+ satisfy the join condition with any row in T2, a joined row is added with null
267+ values in columns of T2. Thus, the joined table always has at least one row for
268+ each row in T1.
269+
270+ .. code-block:: sql
271+ :caption: Left join
272+
273+ SELECT p.title, a.name
274+ FROM poem p
275+ LEFT JOIN author a on p.author_id = a.id;
276+
277+ +------------------------+---------------+
278+ | title | name |
279+ +========================+===============+
280+ | On the Field of Battle | Larysa Kosach |
281+ +------------------------+---------------+
282+ | Moses | Ivan Franko |
283+ +------------------------+---------------+
284+ | The Forest Song | Larysa Kosach |
285+ +------------------------+---------------+
286+ | In the Catacombs | null |
287+ +------------------------+---------------+
288+ | The Singing Stones | Larysa Kosach |
289+ +------------------------+---------------+
290+ | Ancient Fairy Tales | null |
291+ +------------------------+---------------+
292+ | My Thoughts | Ivan Franko |
293+ +------------------------+---------------+
294+ | To Shevchenko | null |
295+ +------------------------+---------------+
296+
297+ RIGHT OUTER JOIN
298+ ----------------
299+
300+ First, an inner join is performed. Then, for each row in T2 that does not
301+ satisfy the join condition with any row in T1, a joined row is added with
302+ null values in columns of T1. This is the converse of a left join: the result
303+ table will always have a row for each row in T2.
304+
305+ .. code-block:: sql
306+ :caption: Right join
307+
308+ SELECT p.title, a.name
309+ FROM poem p
310+ RIGHT JOIN author a on p.author_id = a.id;
311+
312+ +------------------------+---------------+
313+ | title | name |
314+ +========================+===============+
315+ | On the Field of Battle | Larysa Kosach |
316+ +------------------------+---------------+
317+ | Moses | Ivan Franko |
318+ +------------------------+---------------+
319+ | The Forest Song | Larysa Kosach |
320+ +------------------------+---------------+
321+ | The Singing Stones | Larysa Kosach |
322+ +------------------------+---------------+
323+ | My Thoughts | Ivan Franko |
324+ +------------------------+---------------+
325+ | null | John Doe |
326+ +------------------------+---------------+
327+
328+ FULL OUTER JOIN
329+ ---------------
330+
331+ First, an inner join is performed. Then, for each row in T1 that does not
332+ satisfy the join condition with any row in T2, a joined row is added with
333+ null values in columns of T2. Also, for each row of T2 that does not satisfy
334+ the join condition with any row in T1, a joined row with null values in
335+ the columns of T1 is added.
336+
337+ .. code-block:: sql
338+ :caption: Full join
339+
340+ SELECT p.title, a.name
341+ FROM poem p
342+ FULL JOIN author a on p.author_id = a.id;
343+
344+ +------------------------+---------------+
345+ | title | name |
346+ +========================+===============+
347+ | On the Field of Battle | Larysa Kosach |
348+ +------------------------+---------------+
349+ | Moses | Ivan Franko |
350+ +------------------------+---------------+
351+ | The Forest Song | Larysa Kosach |
352+ +------------------------+---------------+
353+ | In the Catacombs | null |
354+ +------------------------+---------------+
355+ | The Singing Stones | Larysa Kosach |
356+ +------------------------+---------------+
357+ | Ancient Fairy Tales | null |
358+ +------------------------+---------------+
359+ | My Thoughts | Ivan Franko |
360+ +------------------------+---------------+
361+ | To Shevchenko | null |
362+ +------------------------+---------------+
363+ | null | John Doe |
364+ +------------------------+---------------+
0 commit comments