2.16: Использование нескольких таблиц в одном SQL запросе
Главная Страница » Книги по PHP » MySQL уроки для начинающих с нуля » Использование нескольких таблиц в одном SQL запросе
Таблица pet описывает, какие домашние животные у вас есть. Если вы хотите записывать другую информацию о них, вроде событий в их жизни: посещений ветеринара или когда рождения потомства, вы нуждаетесь в другой таблице. Что эта таблица должна включать? Требуется:
- имя, чтобы вы знали, к которому животному каждое событие относится;
- дата, чтобы вы знали, когда событие произошло;
- поле, чтобы описать событие;
- поле типа события, если вы хотите разложить события по категориям.
Согласно этим данным, инструкция CREATE TABLE для таблицы событий (event) могла бы выглядеть следующим образом:
mysql> CREATE TABLE event (name VARCHAR(20), date DATE,
-> type VARCHAR(15), remark VARCHAR(255));
Как с таблицей pet, проще всего загрузить начальные записи, создав разграниченный табуляциями текстовый файл, содержащий информацию. Дополнительные данные о зверинце показаны в табл. 2.3:
Таблица 2.3. Дополнительные данные о зверинце.
Fluffy | 1995-05-15 | Потомство | 4 котенка, 3 female, 1 male |
Buffy | 1993-06-23 | Потомство | 5 щенков, 2 female, 3 male |
Buffy | 1994-06-19 | Потомство | 3 щенка, 3 female |
Chirpy | 1999-03-21 | Ветеринар | Необходимо выпрямление клюва |
Slim | 1997-08-03 | Ветеринар | Сломано ребро |
Bowser | 1991-10-12 | Конура | |
Fang | 1991-10-12 | Конура | |
Fang Claws |
1998-08-28 1998-03-17 |
День рождения День рождения |
Подарок: новая жевательная игрушка Подарок: ошейник от блох |
Whistler | 1998-12-09 | День рождения | Первый день рождения |
Загрузите записи так:
mysql> LOAD DATA LOCAL INFILE "event.txt" INTO TABLE event;
Учитывая то, чему вы научились, на запросы к таблице pet, вы должны уметь выполнять поиск по записям в таблице event - принципы те же самые. Но что делать, когда таблица event отдельно недостаточна, чтобы ответить на вопросы, которые вы задает.
Предположим, что вы хотите выяснить для каждого домашнего животного возраст, в котором они имели потомство. Таблица event указываёт, когда это произошло, но чтобы вычислить возраст матери, вы нуждаетесь в ее дате рождения. Поскольку она сохранена в таблице pet, вы нуждаетесь в обеих таблицах для обработки запроса:
mysql> SELECT pet.name, (TO_DAYS(date)-TO_DAYS(birth))/365 AS age,
-> remark FROM pet, event WHERE pet.name=event.name
-> AND type="litter";
+--------+------|-----------------------------|
| name | age | remark |
+--------|------|-----------------------------|
| Fluffy | 2.27 | 4 kittens, 3 female, 1 male |
| Buffy | 4.12 | 5 puppies, 2 female, 3 male |
| Buffy | 5.10 | 3 puppies, 3 female |
+--------|------|-----------------------------|
Итак, что тут происходит?
- предложение FROM указывает сразу две таблицы потому, что запрос должен получить информацию из обеих таблиц;
- при объединении (joining) информации из многих таблиц, вы должны определить, как записи в одной таблице могут быть согласованы с записями в другой. Это просто потому, что они обе имеют столбец nаmе. Запрос использует предложение WHERE, чтобы заставить совпасть записи в двух таблицах, основываясь на значениях паmе;
- поскольку столбец nаmе есть в обеих таблицах, вы должны указать, относительно какой таблицы вы его обозначаете. Это выполняется путем добавления имени таблицы к имени столбца;
- наконец отметим новую функцию TO_DAYS(), которая переводит дату в виде год-месяц-день в число дней.
Вы не обязательно должны иметь две различные таблицы, чтобы выполнить объединение. Иногда полезно присоединить таблицу к самой себе, если вы хотите сравнивать записи в таблице с другими записями в той же самой таблице. Например, чтобы найти размножающиеся пары среди ваших домашних животных, вы можете соединять таблицу pet с самой собой, чтобы объединить самцов и самок одной разновидности.
Но вот проблема: сравнивать таблицу саму с собой по правилам языка SQL нельзя! Однако если очень хочется, то можно обойти ограничение языка. Для этого таблице можно присвоить сразу два псевдонима с помощью уже упомянутого ранее ключевого слова AS и сравнить таблицы под псевдонимами. Тут ограничение не работает: таблицы-то называются по-разному! Например:
mysql> SELECT p1.name, p1.sex, p2.name, p2.sex, p1.species
-> FROM pet AS p1, pet AS p2
-> WHERE p1.species=p2.species AND p1.sex=»f» AND p2.sex=»m»;
+--------+-----|--------|-----|---------|
| name | sex | name | sex | species |
+--------|-----|--------|-----|---------|
| Fluffy | f | Claws | m | кошка |
| Buffy | f | Fang | m | собака |
| Buffy | f | Bowser | m | собака |
+--------|-----|--------|-----|---------|
В этом запросе мы определяем псевдонимы для имени таблицы, чтобы обратиться к столбцам и указываем прямо, с которым образцом таблицы каждая ссылка столбца связана.