Главная страница
Навигация по странице:

  • Сравнение эквисоединений с неэквисоединениями

  • ON e.start_date >= p.date_offered AND e.start_date

  • SELECT e1.fname, e1.lname, VS vs, e2.fname, e2.lname > FROM employee e1 INNER JOIN employee e2 104

  • SELECT e1.fname, e1.lname, VS vs, e2.fname, e2.lname > FROM employee e1 INNER JOIN employee e2 > ON e1.emp_id

  • Сравнение условий соединения и условий фильтрации

  • SELECT a.account_id, a.product_cd, c.fed_id > FROM account a INNER JOIN customer c > ON a.cust_id = c.cust_id > AND c.cust_type_cd = B;

  • SELECT a.account_id, a.product_cd, c.fed_id > FROM account a INNER JOIN customer c > WHERE a.cust_id = c.cust_id > AND c.cust_type_cd = B;

  • Рис. 6.1.

  • Рис. 6.2.

  • Рис. 6.3.

  • Теория множеств на практике

  • SELECT 1 num, abc str > UNION > SELECT 9 num, xyz str

  • Операторы работы с множествами

  • изучаем SQL. Она позволяет решать многошаговые задачи одним выражением


    Скачать 1.6 Mb.
    НазваниеОна позволяет решать многошаговые задачи одним выражением
    Дата09.02.2018
    Размер1.6 Mb.
    Формат файлаpdf
    Имя файлаизучаем SQL.pdf
    ТипДокументы
    #36127
    страница12 из 31
    1   ...   8   9   10   11   12   13   14   15   ...   31
    103
    торого псевдонимы таблиц являются обязательными. В противном случае сервер не сможет определить, на кого делается ссылка – на со трудника или его начальника.
    Хотя в таблице employee 18 строк, по запросу было возвращено только 17.
    У президента банка, Майкла Смита (Michael Smith), нет начальника
    (его столбец superior_emp_id имеет значение null), поэтому для данной строки соединение не сработало. Чтобы включить Майкла Смита в ре зультирующий набор, необходимо использовать внешнее соединение,
    которое будет рассмотрено в главе 10.
    Сравнение эквисоединений
    с неэквисоединениями
    Все запросы к нескольким таблицам, показанные до сих пор, исполь зовали эквисоединения (equi joins). Это означает, что для обеспечения успешности соединения значения двух таблиц должны совпадать. Эк висоединение всегда использует знак равенства, например:
    ON e.assigned_branch_id = b.branch_id
    Подавляющее большинство запросов использует эквисоединения, но можно также соединять таблицы посредством диапазонов значений,
    называемых неэквисоединениями (non equi joins). Вот пример запроса,
    осуществляющего соединение по диапазону значений:
    SELECT e.emp_id, e.fname, e.lname, e.start_date
    FROM employee e INNER JOIN product p
    ON e.start_date >= p.date_offered
    AND e.start_date <= p.date_retired
    WHERE p.name = 'no fee checking';
    Этот запрос соединяет две таблицы, между которыми нет взаимосвя зей по внешним ключам. Задача – найти всех сотрудников, принятых в банк в то время, когда предлагалась услуга беспроцентного текущего вклада. Таким образом, дата начала работы сотрудника должна нахо диться между датами начала и конца этой акции.
    Также может понадобиться рекурсивное неэквисоединение (self non
    equi join
    ), которое означает, что таблица соединяется сама с собой с ис пользованием неэквисоединения. Например, управляющий операция ми решил провести шахматный турнир между всеми операциониста ми банка. Требуется создать список всех пар игроков. Можно попробо вать получить список всех операционистов (title = 'Teller'), соединив таблицу employee с самой собой, и выбрать из него все строки с разными значениями emp_id (поскольку игрок не может составить пару с самим собой):
    mysql> SELECT e1.fname, e1.lname, 'VS' vs, e2.fname, e2.lname
    > FROM employee e1 INNER JOIN employee e2

    104
    Глава 5. Запрос к нескольким таблицам
    > ON e1.emp_id != e2.emp_id
    > WHERE e1.title = 'Teller' AND e2.title = 'Teller';
    +
    +
    +
    +
    +
    +
    | fname | lname | vs | fname | lname |
    +
    +
    +
    +
    +
    +
    | Sarah | Parker | VS | Chris | Tucker |
    | Jane | Grossman | VS | Chris | Tucker |
    | Thomas | Ziegler | VS | Chris | Tucker |
    | Samantha | Jameson | VS | Chris | Tucker |
    | Cindy | Mason | VS | Chris | Tucker |
    | Frank | Portman | VS | Chris | Tucker |
    | Beth | Fowler | VS | Chris | Tucker |
    | Rick | Tulman | VS | Chris | Tucker |
    | Chris | Tucker | VS | Sarah | Parker |
    | Jane | Grossman | VS | Sarah | Parker |
    | Thomas | Ziegler | VS | Sarah | Parker |
    | Samantha | Jameson | VS | Sarah | Parker |
    | Cindy | Mason | VS | Sarah | Parker |
    | Frank | Portman | VS | Sarah | Parker |
    | Beth | Fowler | VS | Sarah | Parker |
    | Rick | Tulman | VS | Sarah | Parker |
    | Chris | Tucker | VS | Rick | Tulman |
    | Sarah | Parker | VS | Rick | Tulman |
    | Jane | Grossman | VS | Rick | Tulman |
    | Thomas | Ziegler | VS | Rick | Tulman |
    | Samantha | Jameson | VS | Rick | Tulman |
    | Cindy | Mason | VS | Rick | Tulman |
    | Frank | Portman | VS | Rick | Tulman |
    | Beth | Fowler | VS | Rick | Tulman |
    +
    +
    +
    +
    +
    +
    72 rows in set (0.01 sec)
    Мы на правильном пути, но проблема здесь в том, что для каждой па ры (например, Сара Паркер (Sarah Parker) против Криса Такера (Chris
    Tucker)) имеется «обратная» пара (т. е. Крис Такер против Сары Пар кер). Один из способов достигнуть желаемого результата – использо вать условие соединения e1.emp_id < e2.emp_id, чтобы каждый опера ционист входил в пару только с теми, у кого ID сотрудника больше
    (можно также использовать e1.emp_id > e2.emp_id, если вам так больше нравится):
    mysql> SELECT e1.fname, e1.lname, 'VS' vs, e2.fname, e2.lname
    > FROM employee e1 INNER JOIN employee e2
    > ON e1.emp_id < e2.emp_id
    > WHERE e1.title = 'Teller' AND e2.title = 'Teller';
    +
    +
    +
    +
    +
    +
    | fname | lname | vs | fname | lname |
    +
    +
    +
    +
    +
    +
    | Chris | Tucker | VS | Sarah | Parker |
    | Chris | Tucker | VS | Jane | Grossman |

    Сравнение условий соединения и условий фильтрации
    105
    | Chris | Tucker | VS | Thomas | Ziegler |
    | Chris | Tucker | VS | Samantha | Jameson |
    | Chris | Tucker | VS | Cindy | Mason |
    | Chris | Tucker | VS | Frank | Portman |
    | Chris | Tucker | VS | Beth | Fowler |
    | Chris | Tucker | VS | Rick | Tulman |
    | Sarah | Parker | VS | Jane | Grossman |
    | Sarah | Parker | VS | Thomas | Ziegler |
    | Sarah | Parker | VS | Samantha | Jameson |
    | Sarah | Parker | VS | Cindy | Mason |
    | Sarah | Parker | VS | Frank | Portman |
    | Sarah | Parker | VS | Beth | Fowler |
    | Sarah | Parker | VS | Rick | Tulman |
    | Jane | Grossman | VS | Thomas | Ziegler |
    | Jane | Grossman | VS | Samantha | Jameson |
    | Jane | Grossman | VS | Cindy | Mason |
    | Jane | Grossman | VS | Frank | Portman |
    | Jane | Grossman | VS | Beth | Fowler |
    | Jane | Grossman | VS | Rick | Tulman |
    | Thomas | Ziegler | VS | Samantha | Jameson |
    | Thomas | Ziegler | VS | Cindy | Mason |
    | Thomas | Ziegler | VS | Frank | Portman |
    | Thomas | Ziegler | VS | Beth | Fowler |
    | Thomas | Ziegler | VS | Rick | Tulman |
    | Samantha | Jameson | VS | Cindy | Mason |
    | Samantha | Jameson | VS | Frank | Portman |
    | Samantha | Jameson | VS | Beth | Fowler |
    | Samantha | Jameson | VS | Rick | Tulman |
    | Cindy | Mason | VS | Frank | Portman |
    | Cindy | Mason | VS | Beth | Fowler |
    | Cindy | Mason | VS | Rick | Tulman |
    | Frank | Portman | VS | Beth | Fowler |
    | Frank | Portman | VS | Rick | Tulman |
    | Beth | Fowler | VS | Rick | Tulman |
    +
    +
    +
    +
    +
    +
    36 rows in set (0.01 sec)
    Теперь у нас есть список из 36 пар. Как раз столько, сколько должно быть при наличии девяти участников.
    Сравнение условий соединения
    и условий фильтрации
    Теперь мы знаем, что условия соединения относятся к подблоку on, то гда как условия фильтрации располагаются в блоке where. Однако SQL
    не налагает жестких ограничений на размещение условий, поэтому соз давать запросы следует очень внимательно. Например, следующий за прос соединяет две таблицы с помощью одного блока соединения и од ного условия фильтрации в блоке where:

    106
    Глава 5. Запрос к нескольким таблицам mysql> SELECT a.account_id, a.product_cd, c.fed_id
    > FROM account a INNER JOIN customer c
    > ON a.cust_id = c.cust_id
    > WHERE c.cust_type_cd = 'B';
    +
    +
    +
    +
    | account_id | product_cd | fed_id |
    +
    +
    +
    +
    | 20 | CHK | 04 1111111 |
    | 21 | BUS | 04 1111111 |
    | 22 | BUS | 04 2222222 |
    | 23 | CHK | 04 3333333 |
    | 24 | SBL | 04 4444444 |
    +
    +
    +
    +
    5 rows in set (0.08 sec)
    Достаточно просто, но что произойдет, если по ошибке поместить усло вие фильтрации в подблок on, а не в блок where?
    mysql> SELECT a.account_id, a.product_cd, c.fed_id
    > FROM account a INNER JOIN customer c
    > ON a.cust_id = c.cust_id
    > AND c.cust_type_cd = 'B';
    +
    +
    +
    +
    | account_id | product_cd | fed_id |
    +
    +
    +
    +
    | 20 | CHK | 04 1111111 |
    | 21 | BUS | 04 1111111 |
    | 22 | BUS | 04 2222222 |
    | 23 | CHK | 04 3333333 |
    | 24 | SBL | 04 4444444 |
    +
    +
    +
    +
    5 rows in set (0.00 sec)
    Как видите, второй вариант, в котором оба условия находятся в подбло ке on и нет блока where, обеспечивает аналогичные результаты. А что ес ли оба условия помещены в блок where, но блок from по прежнему ис пользует ANSI синтаксис соединения?
    mysql> SELECT a.account_id, a.product_cd, c.fed_id
    > FROM account a INNER JOIN customer c
    > WHERE a.cust_id = c.cust_id
    > AND c.cust_type_cd = 'B';
    +
    +
    +
    +
    | account_id | product_cd | fed_id |
    +
    +
    +
    +
    | 20 | CHK | 04 1111111 |
    | 21 | BUS | 04 1111111 |
    | 22 | BUS | 04 2222222 |
    | 23 | CHK | 04 3333333 |
    | 24 | SBL | 04 4444444 |
    +
    +
    +
    +
    5 rows in set (0.00 sec)

    Упражнения
    107
    Сервер MySQL снова сгенерировал тот же результирующий набор. Рас положить условия на соответствующих местах, чтобы запрос был пра вильно понят и обработан, – ваша задача.
    Упражнения
    Следующие упражнения призваны протестировать понимание внут ренних соединений. Решения приведены в приложении С.
    5.1
    Заполните в следующем запросе пробелы (обозначенные как <число>),
    чтобы получить такие результаты:
    mysql> SELECT e.emp_id, e.fname, e.lname, b.name
    > FROM employee e INNER JOIN <1> b
    > ON e.assigned_branch_id = b.<2>;
    +
    +
    +
    +
    +
    | emp_id | fname | lname | name |
    +
    +
    +
    +
    +
    | 1 | Michael | Smith | Headquarters |
    | 2 | Susan | Barker | Headquarters |
    | 3 | Robert | Tyler | Headquarters |
    | 4 | Susan | Hawthorne | Headquarters |
    | 5 | John | Gooding | Headquarters |
    | 6 | Helen | Fleming | Headquarters |
    | 7 | Chris | Tucker | Headquarters |
    | 8 | Sarah | Parker | Headquarters |
    | 9 | Jane | Grossman | Headquarters |
    | 10 | Paula | Roberts | Woburn Branch |
    | 11 | Thomas | Ziegler | Woburn Branch |
    | 12 | Samantha | Jameson | Woburn Branch |
    | 13 | John | Blake | Quincy Branch |
    | 14 | Cindy | Mason | Quincy Branch |
    | 15 | Frank | Portman | Quincy Branch |
    | 16 | Theresa | Markham | So. NH Branch |
    | 17 | Beth | Fowler | So. NH Branch |
    | 18 | Rick | Tulman | So. NH Branch |
    +
    +
    +
    +
    +
    18 rows in set (0.03 sec)
    5.2
    Напишите запрос, по которому для каждого клиента физического ли ца (customer.cust_type_cd = 'I') возвращаются ID счета, федеральный ID
    (customer.fed_id) и тип созданного счета (product.name).
    5.3
    Создайте запрос для выбора всех сотрудников, начальник которых при писан к другому отделу. Извлеките ID, имя и фамилию сотрудника.

    Работа с множествами
    Хотя можно работать и с отдельными строками данных, реляционные
    БД на самом деле приспособлены для работы с наборами (множества ми). Вы уже видели, как можно создавать таблицы посредством запро сов или подзапросов, делать их постоянными с помощью выражений insert и сводить вместе через соединения. В данной главе будут иссле дованы комбинации нескольких таблиц с использованием различных операторов работы с множествами.
    Основы теории множеств
    Во многих странах основы теории множеств включены в программы начального курса математики. Возможно, кое что на рис. 6.1 покажет ся вам знакомым.
    A
    B
    = A union B
    Рис. 6.1. Операция объединения

    Основы теории множеств
    109
    Заштрихованные области на рис. 6.1 представляют объединение (union)
    множеств А и В, которое является комбинацией двух множеств (при этом все пересекающиеся области включены только один раз). Что то припоминаете? Если да, то наконец появился шанс применить эти зна ния на практике. Если нет, не волнуйтесь, потому что без труда пойме те все, взглянув на пару диаграмм.
    Представим множества (А и В) в виде кругов; область перекрытия представляет подмножество данных, общих для обоих множеств
    (рис. 6.1). Поскольку без перекрытий множеств данных теория мно жеств совершенно неинтересна, я буду использовать такую же диа грамму для иллюстрации всех операций с множествами. Есть другая операция, результат которой – только перекрытие двух множеств данных. Эту операцию называют пересечением (intersection) (рис. 6.2).
    Множество данных, получаемое в результате пересечения множеств А
    и В, – это собственно область перекрытия между двумя множествами.
    Если два множества не перекрываются, операция пересечения дает пустое множество.
    Третья и последняя операция с множествами (рис. 6.3) известна как операция разности (except). На рис. 6.3 показан результат операции
    A
    except B, который представляет собой множество А минус все пересе чения с множеством В. Если два множества не пересекаются, в резуль тате операции A except B будет получено полное множество А.
    Применяя эти три операции или их сочетания, можно получать любые нужные результаты. Например, представим, что требуется создать множество, показанное на рис. 6.4.
    Искомое множество включает множества А и В без области пересече ния. Такое множество не может быть получено в результате ни одной из трех представленных ранее операций. Понадобится сначала создать
    A
    B
    = A intersect B
    Рис. 6.2. Операция пересечения

    110
    Глава 6. Работа с множествами множество данных, объединяющее множества А и В целиком, а затем применить вторую операцию, чтобы удалить область пересечения. Ес ли составное множество описать как A union B, а область пересечения –
    как A intersect B, операция, необходимая для формирования представ ленного на рис. 6.4 множества, выглядела бы так:
    (A union B) except (A intersect B)
    Конечно, часто есть несколько способов получения одного и того же результата. Аналогичное множество можно было бы получить с помо щью следующей операции:
    (A except B) union (B except A)
    A
    B
    = A except B
    Рис. 6.3. Операция разности
    A
    B
    = ????
    Рис. 6.4. Загадочное множество данных

    Теория множеств на практике
    111
    Эти концепции, наглядно представленные диаграммами, достаточно просты для понимания. В следующих разделах будет показано, как эти идеи реализуются в реляционных СУБД с помощью SQL операто ров работы с множествами.
    Теория множеств на практике
    Круги, представляющие множества данных на диаграммах предыду щего раздела, никак не отражают содержимое множеств. Однако при работе с реальными данными необходимо описывать структуру таб лиц, если предполагается их комбинирование. Представим, например,
    что произошло бы при попытке сгенерировать объединение описанных ниже таблиц product и customer:
    mysql> DESC product;
    +
    +
    +
    +
    +
    +
    +
    | Field | Type | Null | Key | Default | Extra |
    +
    +
    +
    +
    +
    +
    +
    | product_cd | varchar(10) | | PRI | | |
    | name | varchar(50) | | | | |
    | product_type_cd | varchar(10) | | MUL | | |
    | date_offered | date | YES | | NULL | |
    | date_retired | date | YES | | NULL | |
    +
    +
    +
    +
    +
    +
    +
    5 rows in set (0.23 sec)
    mysql> DESC customer;
    +
    +
    +
    +
    +
    +
    +
    | Field | Type | Null | Key | Default | Extra |
    +
    +
    +
    +
    +
    +
    +
    | cust_id | int(10) unsigned | | PRI | NULL | auto_increment |
    | fed_id | varchar(12) | | | | |
    | cust_type_cd | enum('I','B') | | | I | |
    | address | varchar(30) | YES | | NULL | |
    | city | varchar(20) | YES | | NULL | |
    | state | varchar(20) | YES | | NULL | |
    | postal_code | varchar(10) | YES | | NULL | |
    +
    +
    +
    +
    +
    +
    +
    7 rows in set (0.04 sec)
    После комбинирования первый столбец результирующей таблицы был бы комбинацией столбцов product.product_cd и customer.cust_id, второй –
    комбинацией столбцов product.name и customer.fed_id и т. д. Хотя неко торые пары столбцов сочетаются без труда (т. е. два столбца числового типа), неясно, как должны объединяться пары столбцов разного типа,
    такие как числовой со строковым или строковый с датой. Кроме того,
    в шестом и седьмом столбцах комбинированной таблицы будут только данные шестого и седьмого столбцов таблицы customer, поскольку в таб лице product всего пять столбцов. Очевидно, что таблицы, подлежащие объединению, должны обладать некоторой общностью.

    112
    Глава 6. Работа с множествами
    Поэтому при применении операций с множествами к реальным табли цам необходимо соблюдать такие правила:

    В обеих таблицах должно быть одинаковое число столбцов.

    Типы данных столбцов двух таблиц должны быть одинаковыми
    (или сервер должен уметь преобразовывать один тип в другой).
    Эти правила позволяют уяснить, что представляет собой «перекрытие данных» на практике. Чтобы комбинируемые строки двух таблиц счи тались одинаковыми, каждая пара столбцов комбинируемых таблиц должна содержать одинаковые строки, числа или даты.
    Операции с множествами осуществляются путем помещения операто
    ра работы с множествами
    (set operator) между двух выражений se lect
    , как показано ниже:
    mysql> SELECT 1 num, 'abc' str
    > UNION
    > SELECT 9 num, 'xyz' str;
    +
    +
    +
    | num | str |
    +
    +
    +
    | 1 | abc |
    | 9 | xyz |
    +
    +
    +
    2 rows in set (0.02 sec)
    Каждый запрос формирует таблицу, состоящую из единственной стро ки с числовым и строковым столбцами. Оператор работы с множества ми, в данном случае union, указывает серверу БД объединить все строки двух таблиц. Таким образом, конечная таблица включает две строки и два столбца. Такой запрос называют составным запросом (compound
    query
    ), потому что он объединяет несколько независимых запросов.
    Как будет показано позже, если для получения окончательного ре зультата требуется выполнить несколько операций с множествами, со ставные запросы могут включать больше двух запросов.
    Операторы работы с множествами
    Язык SQL включает три оператора работы с множествами, позволяю щие осуществлять всевозможные операции над множествами, уже упо мянутые в этой главе. Кроме того, у каждого из этих операторов есть две разновидности: первая включает дублирующие данные, а вторая удаляет их (но необязательно все). В следующих разделах даны опреде ления всех операторов и показано их применение.
    1   ...   8   9   10   11   12   13   14   15   ...   31


    написать администратору сайта