alan_beaulieu-learning_sql-ru (865932), страница 12
Текст из файла (страница 12)
Этоне требование MySQL или какогото другого сервера БД, а утвержденный ANSI метод соединения нескольких таблиц, и это способ, наиболее переносимый между серверами БД. Соединение нескольких таблиц будет подробно рассматриваться в главах 5 и 10; здесь приведенлишь простой пример для утоления любопытства:mysql> SELECT employee.emp_id, employee.fname,> employee.lname, department.name dept_name62Глава 3. Азбука запросов> FROM employee INNER JOIN department> ON employee.dept_id = department.dept_id;+++++| emp_id | fname| lname| dept_name|+++++|1 | Michael | Smith| Administration ||2 | Susan| Barker| Administration ||3 | Robert | Tyler| Administration ||4 | Susan| Hawthorne | Operations||5 | John| Gooding | Loans||6 | Helen| Fleming | Operations||7 | Chris| Tucker| Operations||8 | Sarah| Parker| Operations||9 | Jane| Grossman | Operations||10 | Paula| Roberts | Operations||11 | Thomas | Ziegler | Operations||12 | Samantha | Jameson | Operations||13 | John| Blake| Operations||14 | Cindy| Mason| Operations||15 | Frank| Portman | Operations||16 | Theresa | Markham | Operations||17 | Beth| Fowler| Operations||18 | Rick| Tulman| Operations|+++++18 rows in set (0.05 sec)Предыдущий запрос выводит данные из таблиц employee (emp_id, fname,lname) и department (name), поэтому обе таблицы включены в блок from.Механизм связывания двух таблиц (называемый соединением (join))заключается в присоединении данных об отделе, в котором работаетсотрудник, хранящихся в таблице employee.
Таким образом, серверуБД отдается распоряжение использовать значение столбца dept_id таблицы employee для поиска соответствующего названия отдела в таблице department. Условия соединения находятся в подблоке on блока from.В данном случае условие соединения: ON e.dept_id = d.dept_id. Всестороннее обсуждение соединения нескольких таблиц также можно найти в главе 5.Определение псевдонимов таблицПри соединении нескольких таблиц в одном запросе вам понадобитсяидентифицировать таблицу, на которую делается ссылка при указании столбцов в блоках select, where, group by, having и order by.
Датьссылку на таблицу вне блока from можно одним из двух способов:• Использовать полное имя таблицы, например employee.emp_id.• Присвоить каждой таблице псевдоним и использовать его в запросе.В предыдущем запросе я решил использовать в блоках select и on полное имя таблицы. А вот как выглядит этот же запрос с применениемпсевдонимов:63Блок whereSELECT e.emp_id, e.fname, e.lname,d.name dept_nameFROM employee e INNER JOIN department dON e.dept_id = d.dept_id;Если внимательнее посмотреть на блок from, видно, что таблица employee получила псевдоним e, а таблица department – псевдоним d. Затемэти псевдонимы используются в блоке on при описании условия соединения, а также в блоке select при задании столбцов, которые должныбыть включены в результирующий набор.
Надеюсь, все согласятся,что использование псевдонимов делает выражение более компактным,не приводя к путанице (при условии разумного выбора псевдонимов).Блок whereДо сих пор запросы, приводимые в данной главе, осуществляли выборвсех строк из таблиц employee, department или account (кроме примерас ключевым словом distinct). Однако чаще всего извлекать все строкитаблицы не требуется, и нужен способ, позволяющий отфильтровывать строки, не представляющие интереса. Это работа для блока where.Блок where – это механизм отсеивания нежелательных строкиз результирующего набора.Например, требуется извлечь из таблицы employee данные, но толькодля сотрудников, нанятых в качестве старших операционистов (headtellers). В следующем запросе блок where служит для извлечения только четырех старших операционистов:mysql> SELECT emp_id, fname, lname, start_date, title> FROM employee> WHERE title = 'Head Teller';++++++| emp_id | fname | lname | start_date | title|++++++|6 | Helen | Fleming | 20040317 | Head Teller ||10 | Paula | Roberts | 20020727 | Head Teller ||13 | John| Blake | 20000511 | Head Teller ||16 | Theresa | Markham | 20010315 | Head Teller |++++++4 rows in set (0.00 sec)В данном случае блоком where были отсеяны 14 из 18 строк.
Этот блокwhere содержит всего одно условие фильтрации (filter condition), но этихусловий может быть столько, сколько потребуется. Условия разделяются с помощью таких операторов, как and, or и not (подробно блок whereи условия фильтрации обсуждаются в главе 4). Вот расширенный вариант предыдущего запроса со вторым условием – должны быть включены только сотрудники, принятые на работу после 1 января 2002 года:64Глава 3. Азбука запросовmysql> SELECT emp_id, fname, lname, start_date, title> FROM employee> WHERE title = 'Head Teller'> AND start_date > '20020101';++++++| emp_id | fname | lname | start_date | title|++++++|6 | Helen | Fleming | 20040317 | Head Teller ||10 | Paula | Roberts | 20020727 | Head Teller |++++++2 rows in set (0.00 sec)По первому условию (title = 'Head Teller') было отфильтровано 14 из 18строк, а по второму (start_date > '20020101') – еще 2.
В итоге в результирующем наборе осталось 2 строки. Давайте посмотрим, что произойдет, если заменить разделяющий условия оператор and оператором or:mysql> SELECT emp_id, fname, lname, start_date, title> FROM employee> WHERE title = 'Head Teller'> OR start_date > '20020101';++++++| emp_id | fname| lname| start_date | title|++++++|2 | Susan| Barker| 20020912 | Vice President||4 | Susan| Hawthorne | 20020424 | Operations Manager ||5 | John| Gooding | 20031114 | Loan Manager||6 | Helen| Fleming | 20040317 | Head Teller||7 | Chris| Tucker| 20040915 | Teller||8 | Sarah| Parker| 20021202 | Teller||9 | Jane| Grossman | 20020503 | Teller||10 | Paula| Roberts | 20020727 | Head Teller||12 | Samantha | Jameson | 20030108 | Teller||13 | John| Blake| 20000511 | Head Teller||14 | Cindy| Mason| 20020809 | Teller||15 | Frank| Portman | 20030401 | Teller||16 | Theresa | Markham | 20010315 | Head Teller||17 | Beth| Fowler| 20020629 | Teller||18 | Rick| Tulman| 20021212 | Teller|++++++15 rows in set (0.00 sec)Посмотрев на выходные данные, можно увидеть, что в результирующий набор включены все четыре старших операциониста (Head Teller), а также все остальные сотрудники, приступившие к работе в банке после 1 января 2002 года.
Для 15 из 18 сотрудников из таблицыemployee выполняется по крайней мере одно из двух условий. Такимобразом, чтобы строка попала в результирующий набор, когда условияразделяются оператором and, для нее должны выполняться все условия; а при использовании оператора or достаточно, чтобы выполнялось только одно из условий.Блоки group by и having65А как быть, если вам нужно задействовать в блоке where оба оператора –and и or? Рад, что спросили.
Необходимо сгруппировать условия с помощью круглых скобок. Следующий запрос составлен так, что в результирующий набор должны попасть только те сотрудники, которыеявляются старшими операционистами (Head Teller) и начали работатьв компании позже 1 января 2002 года, или простые операционисты (Teller), начавшие работать после 1 января 2003 года:mysql> SELECT emp_id, fname, lname, start_date, title> FROM employee> WHERE (title = 'Head Teller' AND start_date > '20020101')> OR (title = 'Teller' AND start_date > '20030101');++++++| emp_id | fname| lname | start_date | title|++++++|6 | Helen| Fleming | 20040317 | Head Teller ||7 | Chris| Tucker | 20040915 | Teller||10 | Paula| Roberts | 20020727 | Head Teller ||12 | Samantha | Jameson | 20030108 | Teller||15 | Frank| Portman | 20030401 | Teller|++++++5 rows in set (0.00 sec)Для разделения групп условий при использовании различных операторов всегда следует применять круглые скобки, чтобы автор запроса,сервер БД и любой специалист, который позже будет работать с этимкодом, понимали, что происходит.Блоки group by и havingВсе рассмотренные до сих пор запросы извлекали необработанные строки данных, не выполняя над ними никаких действий.
Однако иногдавам захочется выявить в данных общие направления, для чего серверуБД придется немного поколдовать над ними, прежде чем предоставитьвам результирующий набор. Одним из средств для этого является блокgroup by, предназначенный для группировки данных по значениямстолбцов.
Например, вместо списка сотрудников и отделов, в которыхони числятся, нужен список отделов с числом сотрудников, работающих в каждом из них. С блоком group by также можно использоватьблок having, позволяющий фильтровать данные групп аналогично блоку where, позволяющему фильтровать необработанные данные.Я хотел лишь слегка коснуться этих двух блоков, чтобы в дальнейшемони не были неожиданностью для читателей, но они немного сложнее,чем другие четыре блока выражения select.