# Главная
# О библиотеке

# Выбор дистрибутива
преимущества Linux/UNIX | основные дистрибутивы | серверный Linux | BSD | LiveCDs | прочее

# Установка и удаление программ
общие вопросы | каталоги софта | специальные случаи

# Настройка и работа
установка, загрузчики | настройка Linux | консоль | файловые системы | процессы | шеллы, русификация, коммандеры | виртуальные машины, эмуляторы

# X Window и оконные менеджеры
настройка X Window | GNOME | KDE | IceWM и др.

# Работа с текстами
редакторы | офис | шрифты, кодировки и русификация | преобразования текстовых файлов | LaTeX, SGML и др. | словари

# Графика
GIMP | фото | обработка изображений | форматы графических файлов

# Сети, администрирование
общие вопросы | Dialup & PPP | брандмауэры | маршрутизация | работа в Windows-сетях | веб-серверы | Apache | прокси-серверы | сетевая печать | прочее

# Программирование
GCC & GNU make | программирование в UNIX | графические библиотеки | Tcl | Perl | PHP | Java & C# | СУБД | CVS | прочее

# Ядро
# Мультимедиа
# Интернет
# Почта
# Безопасность
# Железо
# Разное

# Linux HowTo (как сделать)
# Книги и руководства
# Материалы на английском языке


MySQL The World's Most Popular Open Source Database # Online shop | Site map |  
CompanyProductsSupport & ConsultingTraining & CertificationDownloadsDocumentation
  BooksArticlesMailing ListsPresentationsOther Sites  
Search the MySQL manual:
MySQL Manual
  • 6 Справочник по языку MySQL
    • 6.4 Обработка данных: SELECT, INSERT, UPDATE, DELETE
      • 6.4.1 Синтаксис оператора SELECT
        • 6.4.1.1 Синтаксис оператора JOIN
        • 6.4.1.2 Синтаксис оператора UNION

Buy this Reference Manual in softcover from Barnes & Noble!

MySQL Reference Manual
Previous / Next / Up / Table of Contents

6.4.1.1 Синтаксис оператора JOIN

MySQL поддерживает следующий синтаксис оператора JOIN при использовании в командах SELECT:

table_reference, table_reference
table_reference [CROSS] JOIN table_reference
table_reference INNER JOIN table_reference join_condition
table_reference STRAIGHT_JOIN table_reference
table_reference LEFT [OUTER] JOIN table_reference join_condition
table_reference LEFT [OUTER] JOIN table_reference
table_reference NATURAL [LEFT [OUTER]] JOIN table_reference
{ oj table_reference LEFT OUTER JOIN table_reference ON conditional_expr }
table_reference RIGHT [OUTER] JOIN table_reference join_condition
table_reference RIGHT [OUTER] JOIN table_reference
table_reference NATURAL [RIGHT [OUTER]] JOIN table_reference

где table_reference определено, как:

table_name [[AS] alias] [USE INDEX (key_list)] [IGNORE INDEX (key_list)]

и join_condition определено, как:

ON conditional_expr |
USING (column_list)

Никогда не следует указывать в части ON какие бы то ни было условия, накладывающие ограничения на строки в наборе результатов. Если необходимо указать, какие строки должны присутствовать в результате, следует сделать это в выражении WHERE.

Необходимо учитывать, что в версиях до 3.23.17 оператор INNER JOIN не принимает параметр join_condition!

Наличие последней из приведенных выше конструкций выражения LEFT OUTER JOIN обусловлено только требованиями совместимости с ODBC:

  • Вместо ссылки на таблицу может использоваться псевдоним, который присваивается при помощи выражений tbl_name AS alias_name или tbl_name alias_name:
    mysql> SELECT t1.name, t2.salary FROM employee AS t1, info AS t2
            WHERE t1.name = t2.name;
    
  • Условный оператор ON представляет собой условие в любой форме из числа тех, которые можно использовать в выражении WHERE.
  • Если запись для правой таблицы в частях ON или USING в LEFT JOIN не найдена, то для данной таблицы используется строка, в которой все столбцы установлены в NULL. Эту возможность можно применять для нахождения результатов в таблице, не имеющей эквивалента в другой таблице:
    mysql> SELECT table1.* FROM table1
            LEFT JOIN table2 ON table1.id=table2.id
            WHERE table2.id IS NULL;
    
    Этот пример находит все строки в таблице table1 с величиной id, которая не присутствует в таблице table2 (т.е. все строки в table1, для которых нет соответствующих строк в table2). Конечно, это предполагает, что table2.id объявлен как NOT NULL. See section 5.2.6 Как MySQL оптимизирует LEFT JOIN и RIGHT JOIN.
  • USING (column_list) служит для указания списка столбцов, которые должны существовать в обеих таблицах. Такое выражение USING, как:
    A LEFT JOIN B USING (C1,C2,C3,...)
    
    семантически идентично выражению ON, например:
    A.C1=B.C1 AND A.C2=B.C2 AND A.C3=B.C3,...
    
  • Выражение NATURAL [LEFT] JOIN для двух таблиц определяется так, чтобы оно являлось семантическим эквивалентом INNER JOIN или LEFT JOIN с выражением USING, в котором указаны все столбцы, имеющиеся в обеих таблицах.
  • INNER JOIN и , (запятая) являются семантическими эквивалентами. Оба осуществляют полное объединение используемых таблиц. Способ связывания таблиц обычно задается в условии WHERE.
  • RIGHT JOIN работает аналогично LEFT JOIN. Для сохранения переносимости кода между различными базами данных рекомендуется вместо RIGHT JOIN использовать LEFT JOIN.
  • STRAIGHT_JOIN идентично JOIN, за исключением того, что левая таблица всегда читается раньше правой. Это выражение может использоваться для тех (немногих) случаев, когда оптимизатор объединения располагает таблицы в неправильном порядке.
  • Начиная с версии MySQL 3.23.12, можно давать MySQL указания о том, какой индекс должен использоваться при извлечении информации из таблицы. Эта возможность полезна, если оператор EXPLAIN (выводящий информацию о структуре и порядке выполнения запроса SELECT), показывает, что MySQL использует ошибочный индекс. Задавая значение индекса в USE INDEX (key_list), можно заставить MySQL применять для поиска записи только один из указанных индексов. Альтернативное выражение IGNORE INDEX (key_list) запрещает использование в MySQL данного конкретного индекса. Выражения USE/IGNORE KEY являются синонимами для USE/IGNORE INDEX.

Несколько примеров:

mysql> SELECT * FROM table1,table2 WHERE table1.id=table2.id;
mysql> SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id;
mysql> SELECT * FROM table1 LEFT JOIN table2 USING (id);
mysql> SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id
        LEFT JOIN table3 ON table2.id=table3.id;
mysql> SELECT * FROM table1 USE INDEX (key1,key2)
        WHERE key1=1 AND key2=2 AND key3=3;
mysql> SELECT * FROM table1 IGNORE INDEX (key3)
        WHERE key1=1 AND key2=2 AND key3=3;

See section 5.2.6 Как MySQL оптимизирует LEFT JOIN и RIGHT JOIN.

User Comments

Posted by [name withheld] on Friday July 5 2002, @5:17am[Delete] [Edit]

An example of an inner join on more than two tables
would be useful here. And maybe an explanation of
why the following is important.

If the order is not correct you'll get a syntax error. If
you have a FROM clause with the following pattern:

FROM table1 INNER JOIN (some other join) ON (join
condition).

Change it to:
FROM (some other join) INNER JOIN table1 ON (join
condition).

Posted by Csaba Gabor on Wednesday December 18 2002, @5:27pm[Delete] [Edit]

The join_condition is used for winnowing the
rows of the "right half" that you want to use for
the cross, whereas the WHERE clause is used for
winnowing the composite.

For example, suppose we have a table Men (Man
varchar(15), Lover(15)) and we want to find all
men who had Daisy as a Lover, but not Petunia.
Then we might use:

SELECT M1.Man FROM Men AS M1 LEFT JOIN
Men AS
M2
ON M1.Man=M2.Man AND M2.Lover='Petunia'
WHERE M1.Lover='Daisy' AND M2.Lover IS NULL;

The second part on the ON ensures that we get
NULLs on the right side when Petunia is missing
while the second part of the where picks out
those rows where we actually did get the NULL.

Posted by [name withheld] on Wednesday December 18 2002, @5:27pm[Delete] [Edit]

You can refer to the same table more than once by using table aliases. A common example would be when you have a staff table that contains both staff and manager's details. If you wanted a list of staff, with their corresponding manager's details as well, you would refer to the same table twice.
eg.
SELECT s1.StaffId, s1.StaffName, s1.Position, s1.ManagerId, s2.StaffName AS ManagerName, s2.Position AS ManagerPosition
FROM staff AS s1 INNER JOIN staff AS s2 ON(s1.ManagerId=s2.StaffId)

This can work multiple times, referring back to the same table. You can also join with other tables as normal at the same time, although you need to specify which table alias (and thus which rows, eg. the manager's or the staff's) you would like to join on.

Posted by [name withheld] on Wednesday December 18 2002, @5:27pm[Delete] [Edit]

You want to select all rows from table1 which don't exist in table 2?
Example:
table1.id = list(1, 2, 3, 4, 5)
table2.id = list(1, 2, 5)
You want to have 3 and 4 as the result cause they are not in table 2?
Use the OUTER JOIN:
SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id WHERE table2.id IS NULL

Posted by Paul Dodd on Monday September 30 2002, @7:33am[Delete] [Edit]

Note that the form USING (X,Y) does not give the same results as the long form e.g. U ON (W.X = U.X AND W.Y = U.Y) when LEFT JOINing multiple tables. I suppose this is because with USING
the left table is used for the comparison whereas with ON the specified table is used ...

Posted by David Martin on Wednesday December 18 2002, @5:27pm[Delete] [Edit]

This comment got deleted at some point so I'm
adding it back. Probably simular to comment 1.
This gave me trouble for a while so I thought I'd
pass it on. If you want a left join with a
condition for the right table (the row that may
or may not be there) you have to put the
condition in the join clause, not the where
clause.

Here's an example:
SELECT
*
FROM
t1 LEFT JOIN t2 on (t1.id_t1 =
t2.id_t1
AND t2.id_t2 = 345)
WHERE
t1.id_level=17 ;

I appologize if that's common knowledge but this
note would have saved me hours.
Thanks

Posted by [name withheld] on Wednesday November 20 2002, @4:33am[Delete] [Edit]

Thank you David Martin, as your 'obsolete' note
helped me finish my query :)

Posted by Alan G-B on Wednesday December 18 2002, @5:27pm[Delete] [Edit]

I've seen requests for joining more than two
tables.
This goes a little further in that it joins three tables,
one of which is aliased three times.

The advert table contains adverts in which there
are
three region fields - region1,region2,region3; and a
category field.

Both the region and category tables have a key
id
field to join to the adverts table and a description
field.

The SQL is as follows...


SELECT adverts.*, categories.description AS
cat_desc, regions_1.description AS
region1_desc,regions_2.description AS
region2_desc,regions_3.description AS region3_desc
FROM adverts
RIGHT JOIN regions AS regions_3 ON
regions_3.regionID=adverts.region3
RIGHT JOIN regions AS regions_2 ON
regions_2.regionID=adverts.region2
RIGHT JOIN regions AS regions_1 ON
regions_1.regionID=adverts.region1
INNER JOIN categories ON
categories.categoryID=adverts.categoryID

This results in records showing all adverts with
the relevant descriptive text for each region and the
category.
It is a little slow, so if any one knows of a way
to speed it up...

Posted by [email protected] on Tuesday January 7 2003, @5:35pm[Delete] [Edit]

Why do you need JOINs for the above example? Couldn't you just do:

SELECT adverts.*, categories.description AS
cat_desc, regions_1.description AS
region1_desc, regions_2.description AS
region2_desc, regions_3.description AS region3_desc
FROM adverts, regions AS regions_1, regions AS regions_2, regions AS regions_3, categories
WHERE regions_3.regionID=adverts.region3
AND regions_2.regionID=adverts.region2
AND regions_1.regionID=adverts.region1
AND categories.categoryID=adverts.categoryID;

Or am I insane?

Posted by Scott Atkins on Thursday January 23 2003, @8:43am[Delete] [Edit]

Tip time:

(Background: This database is used to keep track of scores for students in my classes.)

So in this case, I have three tables, one has student's "codename" (as posting their real name on the web is a no-no) and an index (there is more data in this table, but this is all you really need to know.) Then there's a table with the assignments, containing the assignment name, and an index for each assignment. Finally, there is a scores table, which has for each paper I get turned in, a student_id (releated to the student index) an act_id (related to the assignments index) and a score.

It looked something like this:
students table:
+----+---------------+
| id | codename |
+----+---------------+
| 1 | Budy |
+----+---------------+

assignments table:
+--------+------------+
| act_id | name |
+--------+------------+
| 1 | Activity 1 |
| 2 | Activity 2 |
+--------+------------+

scores table:
+------------+--------+-------+
| student_id | act_id | score |
+------------+--------+-------+
| 1 | 1 | 10 |
| 1 | 2 | 10 |
+------------+--------+-------+

Now the problem was, I wanted to have the assignments listed across the top, and the scores next to the names. Something like this:
+---------------+------------+------------+-------+
| codename | Activity 1 | Activity 2 | Total |
+---------------+------------+------------+-------+
| budy | 10 | 10 | 20 |
+---------------+------------+------------+-------+

So here's how the sql statement ended up:
SELECT names.codename,
s1.score AS "Score1", s1.comment AS "Comments1",
s2.score AS "Score2", s2.comment AS "Comments2",
SUM(st.score) AS "Total"
FROM students names
LEFT JOIN scores s1 ON s1.act_id=1 AND names.id=s1.student_id
LEFT JOIN scores s2 ON s2.act_id=2 AND names.id=s2.student_id
LEFT JOIN scores st ON names.id=st.student_id
WHERE names.codename <> ''
GROUP BY names.codename
ORDER BY names.codename;

As you can see, for each activity, I need to add another left join, but it looks exactly like the last one, thus it is easy to build through a program like php. I hope this helps someone out.

Posted by trevor on Wednesday March 5 2003, @10:41am[Delete] [Edit]

equivalent of *= in mySQL

I was trying to convert this SQL statement to mySQL:

$sql = "select * from table1,table2 where topicID = '$topicID' and table1.CommentID *= table2.replyCommentID" ;

this is what I came up with after much trial & error:

$sql = "select * from table1 LEFT JOIN table2 ON table1.commentID=table2.replyCommentID where table1.topicID = '$topicID' " ;

here it is in action: http://www.groovything.com/default.php?menu=c&subM=d_f&css=05&page=forum&action=view&topicID=1

Hopefully this will be useful info. I was wishing it was out there when I needed it so I decided to post it in case anyone else has a similar question

Add your own comment.

Top / Previous / Next / Up / Table of Contents
# MySQL.com home | Site map | Contact us | Press | Jobs | Privacy policy | Trademark info | © 1995-2003 MySQL AB. All rights reserved.