diff --git a/doc/src/sgml/query.sgml b/doc/src/sgml/query.sgml
index c0889743c4..6f8ea373b5 100644
--- a/doc/src/sgml/query.sgml
+++ b/doc/src/sgml/query.sgml
@@ -441,11 +441,11 @@ SELECT DISTINCT city
Thus far, our queries have only accessed one table at a time.
Queries can access multiple tables at once, or access the same
- table in such a way that multiple rows of the table are being
- processed at the same time. A query that accesses multiple rows
- of the same or different tables at one time is called a
- join query. As an example, say you wish to
- list all the weather records together with the location of the
+ table several times. Such queries — they are called
+ join queries — combine
+ rows of one table in some way with rows of the other table
+ and return a single row per combination. An example may be a
+ list of all the weather records together with the location of the
associated city. To do that, we need to compare the city
column of each row of the weather table with the
name column of all rows in the cities
@@ -461,10 +461,17 @@ SELECT DISTINCT city
SELECT *
- FROM weather, cities
- WHERE city = name;
+FROM weather
+JOIN cities ON (city = name);
+ The keyword JOIN connects the two tables.
+ Behind the keyword ON follows the
+ definition how to compare their rows. In this case, the
+ column city of table weather
+ must be equal to the column name
+ of table cities.
+
city | temp_lo | temp_hi | prcp | date | name | location
---------------+---------+---------+------+------------+---------------+-----------
@@ -476,8 +483,14 @@ SELECT *
- Observe two things about the result set:
+ Observe some things about the result set:
+
+
+ The resulting rows contain values from both tables.
+
+
+
There is no result row for the city of Hayward. This is
@@ -499,8 +512,8 @@ SELECT *
*:
SELECT city, temp_lo, temp_hi, prcp, date, location
- FROM weather, cities
- WHERE city = name;
+FROM weather
+JOIN cities ON (city = name);
@@ -509,10 +522,9 @@ SELECT city, temp_lo, temp_hi, prcp, date, location
Exercise:
-
Attempt to determine the semantics of this query when the
- WHERE clause is omitted.
+ ON clause is omitted.
@@ -526,8 +538,8 @@ SELECT city, temp_lo, temp_hi, prcp, date, location
SELECT weather.city, weather.temp_lo, weather.temp_hi,
weather.prcp, weather.date, cities.location
- FROM weather, cities
- WHERE cities.name = weather.city;
+FROM weather
+JOIN cities ON (cities.name = weather.city);
It is widely considered good style to qualify all column names
@@ -537,20 +549,22 @@ SELECT weather.city, weather.temp_lo, weather.temp_hi,
Join queries of the kind seen thus far can also be written in this
- alternative form:
+ form:
SELECT *
- FROM weather INNER JOIN cities ON (weather.city = cities.name);
+FROM weather, cities
+WHERE weather.city = cities.name;
- This syntax is not as commonly used as the one above, but we show
- it here to help you understand the following topics.
+ This syntax is not as commonly used as the one above. It dates back
+ to the very first times of SQL, avoids the JOIN
+ keyword and uses the WHERE clause instead of the
+ ON clause.
+ joinouter
- joinouter
-
Now we will figure out how we can get the Hayward records back in.
What we want the query to do is to scan the
weather table and for each row to find the
@@ -563,15 +577,19 @@ SELECT *
SELECT *
- FROM weather LEFT OUTER JOIN cities ON (weather.city = cities.name);
+FROM weather
+LEFT OUTER JOIN cities ON (weather.city = cities.name);
+
+
+
city | temp_lo | temp_hi | prcp | date | name | location
---------------+---------+---------+------+------------+---------------+-----------
Hayward | 37 | 54 | | 1994-11-29 | |
San Francisco | 46 | 50 | 0.25 | 1994-11-27 | San Francisco | (-194,53)
San Francisco | 43 | 57 | 0 | 1994-11-29 | San Francisco | (-194,53)
(3 rows)
-
+
This query is called a left outer
join because the table mentioned on the left of the
@@ -591,10 +609,9 @@ SELECT *
+ joinself
+ aliasfor table name in query
- joinself
- aliasfor table name in query
-
We can also join a table against itself. This is called a
self join. As an example, suppose we wish
to find all the weather records that are in the temperature range
@@ -607,30 +624,42 @@ SELECT *
following query:
-SELECT W1.city, W1.temp_lo AS low, W1.temp_hi AS high,
- W2.city, W2.temp_lo AS low, W2.temp_hi AS high
- FROM weather W1, weather W2
- WHERE W1.temp_lo < W2.temp_lo
- AND W1.temp_hi > W2.temp_hi;
+SELECT w1.city, w1.temp_lo AS low, w1.temp_hi AS high,
+ w2.city, w2.temp_lo AS low, w2.temp_hi AS high
+FROM weather w1
+JOIN weather w2 ON (w1.temp_lo < w2.temp_lo AND
+ w1.temp_hi > w2.temp_hi);
+
+
city | low | high | city | low | high
---------------+-----+------+---------------+-----+------
San Francisco | 43 | 57 | San Francisco | 46 | 50
Hayward | 37 | 54 | San Francisco | 46 | 50
(2 rows)
-
+
- Here we have relabeled the weather table as W1 and
- W2 to be able to distinguish the left and right side
+ Here we have relabeled the weather table as w1 and
+ w2 to be able to distinguish the left and right side
of the join. You can also use these kinds of aliases in other
queries to save some typing, e.g.:
SELECT *
- FROM weather w, cities c
- WHERE w.city = c.name;
+FROM weather w
+JOIN cities c ON (w.city = c.name);
You will encounter this style of abbreviating quite frequently.
+
+
+
+ The examples shown here combine rows via city names.
+ This should help to understand the concept. Professional
+ solutions prefer to use numerical IDs and foreign keys
+ to join tables.
+
+
+