Урок 14 Êîìáèíèðîâàííûå çàïðîñû  ýòîì óðîêå âû óçíàåòå, êàê èñïîëüçîâàòü îïåðàòîð UNION äëÿ êîìáèíèðîâàíèÿ ìíîãèõ îïåðàòîðîâ SELECT ñ öåëüþ ïîëó÷åíèÿ îäíîãî íàáîðà ðåçóëüòàòîâ. ×òî òàêîå êîìáèíèðîâàííûå çàïðîñû  áîëüøèíñòâå SQL-çàïðîñîâ èñïîëüçóåòñÿ îäèí îïåðàòîð, ïîñðåäñòâîì êîòîðîãî âîçâðàùàþòñÿ äàííûå èç îäíîé èëè íåñêîëüêèõ òàáëèö. SQL ïîçâîëÿåò òàêæå âûïîëíÿòü ìíîæåñòâåííûå çàïðîñû (çà ñ÷åò ìíîãîêðàòíîãî èñïîëüçîâàíèÿ îïåðàòîðà SELECT) è âîçâðàùàòü ðåçóëüòàòû â âèäå îäíîãî íàáîðà ðåçóëüòàòîâ çàïðîñà. Ýòè êîìáèíèðîâàííûå çàïðîñû îáû÷íî íàçûâàþò ñîåäèíåíèÿìè èëè ñëîæíûìè çàïðîñàìè. Ìîæíî íàçâàòü äâà îñíîâíûõ ñöåíàðèÿ, äëÿ âûïîëíåíèÿ êîòîðûõ âàì ïîíàäîáÿòñÿ ñëîæíûå çàïðîñû: äëÿ âîçâðàùåíèÿ îäèíàêîâûì îáðàçîì ñòðóêòóðèðîâàííûõ äàííûõ èç ðàçëè÷íûõ òàáëèö ïîñðåäñòâîì îäíîãî çàïðîñà; äëÿ âûïîëíåíèÿ ìíîãîêðàòíûõ çàïðîñîâ ê îäíîé òàáëèöå è âîçâðàùåíèÿ äàííûõ â âèäå ðåçóëüòàòà îäíîãî çàïðîñà. 146 Урок 14 Комбинированные запросы и многократные условия WHERE Результат комбинирования двух запросов к одной и той же таблице в основном аналогичен результату, полученному при выполнении одного запроса с несколькими требованиями в предложении WHERE. Иначе говоря, как будет показано в следующем разделе, любой оператор SELECT с многократно используемым условием WHERE можно также рассматривать как сложный запрос. Ñîçäàíèå êîìáèíèðîâàííûõ çàïðîñîâ Çàïðîñû â ÿçûêå SQL êîìáèíèðóþòñÿ ñ ïîìîùüþ îïåðàòîðà UNION. Îïåðàòîð UNION ïîçâîëÿåò ìíîãîêðàòíî óêàçûâàòü îïåðàòîð SELECT, è ïî çàâåðøåíèè èõ ðàáîòû ìîæåò áûòü âûâåäåí îäèí íàáîð ðåçóëüòàòîâ. Èñïîëüçîâàíèå îïåðàòîðà UNION Èñïîëüçîâàòü îïåðàòîð UNION äîâîëüíî ïðîñòî. Âñå, ÷òî âû äîëæíû ñäåëàòü, — ýòî óêàçàòü êàæäûé íåîáõîäèìûé âàì îïåðàòîð SELECT è ðàçìåñòèòü êëþ÷åâîå ñëîâî UNION ìåæäó íèìè. Ðàññìîòðèì ïðèìåð. Äîïóñòèì, âàì íåîáõîäèì îò÷åò, ñîäåðæàùèé ñâåäåíèÿ îáî âñåõ êëèåíòàõ èç øòàòîâ Èëëèíîéñ, Èíäèàíà è Ìè÷èãàí. Âû òàêæå õîòèòå âêëþ÷èòü â íåãî äàííûå î êëèåíòå Fun4All íåçàâèñèìî îò øòàòà. Êîíå÷íî, ìîæíî ñîçäàòü óñëîâèå WHERE, áëàãîäàðÿ êîòîðîìó áóäåò âûïîëíåíî òðåáóåìîå, íî â äàííîì ñëó÷àå ãîðàçäî óäîáíåå èñïîëüçîâàòü îïåðàòîð UNION. Êàê óæå ãîâîðèëîñü, ïðèìåíåíèå îïåðàòîðà UNION ïîäðàçóìåâàåò ìíîãîêðàòíîå èñïîëüçîâàíèå îïåðàòîðîâ SELECT. Âíà÷àëå ðàññìîòðèì îòäåëüíûå îïåðàòîðû: Комбинированные запросы 147 ВВОД SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_state IN ('IL','IN','MI'); ВЫВОД cust_name ----------Village Toys Fun4All The Toy Store cust_contact ------------John Smith Jim Jones Kim Howard cust_email [email protected] [email protected] NULL ВВОД SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_name = 'Fun4All'; ВЫВОД cust_name --------Fun4All Fun4All cust_contact -----------Jim Jones Denise L. Stephens cust_email [email protected] [email protected] Анализ Ïåðâûé îïåðàòîð SELECT âûáèðàåò âñå ñòðîêè, îòíîñÿùèåñÿ ê øòàòàì Èëëèíîéñ, Èíäèàíà è Ìè÷èãàí, ïåðåäàâàÿ àááðåâèàòóðû ýòèõ øòàòîâ â óñëîâèå IN. Âòîðîé îïåðàòîð SELECT èñïîëüçóåò ïðîñòóþ ïðîâåðêó íà ðàâåíñòâî, ÷òîáû íàéòè âñå ìåñòîíàõîæäåíèÿ â òàáëèöàõ êëèåíòà Fun4All. ×òîáû ñêîìáèíèðîâàòü ýòè äâà çàïðîñà, âûïîëíèòå ñëåäóþùåå. ВВОД SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_state IN ('IL','IN','MI') UNION SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_name = 'Fun4All'; 148 Урок 14 ВЫВОД cust_name --------Fun4All Fun4All Village The Toy Store cust_contact -----------Denise L.Stephens Jim Jones Toys John Smith Kim Howard cust_email [email protected] [email protected] [email protected] NULL Анализ Îïåðàòîðû ïðåäûäóùåãî ïðèìåðà ñîñòîÿò èç îáîèõ ïðåäøåñòâóþùèõ îïåðàòîðîâ SELECT, ðàçäåëåííûõ êëþ÷åâûì ñëîâîì UNION. Îïåðàòîð UNION óêàçûâàåò ÑÓÁÄ âûïîëíèòü îáà îïåðàòîðà SELECT è âûâåñòè ðåçóëüòàòû â âèäå îäíîãî íàáîðà ðåçóëüòàòîâ çàïðîñà. Äëÿ ñðàâíåíèÿ ïðèâîäèì òîò æå ñàìûé çàïðîñ, èñïîëüçóþùèé íå îïåðàòîð UNION, à íåñêîëüêî ïðåäëîæåíèé WHERE: ВВОД SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_state IN ('IL','IN','MI') OR cust_name = 'Fun4All';  íàøåì ïðîñòîì ïðèìåðå ïðèìåíåíèå îïåðàòîðà UNION ìîæåò îêàçàòüñÿ áîëåå ñëîæíûì, ÷åì èñïîëüçîâàíèå ïðåäëîæåíèÿ WHERE. Îäíàêî åñëè óñëîâèå ôèëüòðàöèè îêàæåòñÿ áîëåå ñëîæíûì èëè åñëè ïîíàäîáèòñÿ âûáèðàòü äàííûå èç ìíîãèõ òàáëèö (à íå òîëüêî èç îäíîé), òî îïåðàòîð UNION ìîæåò çíà÷èòåëüíî óïðîñòèòü ïðîöåññ. Ограничения оператора UNION В стандартном SQL не существует ограничений на число операторов SELECT, которые могут быть скомбинированы посредством операторов UNION. Однако лучше все же обратиться к документации СУБД и убедиться в том, что она не накладывает каких-либо ограничений на максимально допустимое число операторов. Комбинированные запросы Проблемы, 149 связанные с производительностью В большинстве хороших СУБД используется внутренний оптимизатор запросов, комбинирующий операторы SELECT, прежде чем СУБД начинает их обработку. Теоретически это означает, что, с точки зрения производительности, нет реальной разницы между использованием многих предложений WHERE и оператора UNION. Мы говорим “теоретически”, потому что на практике многие оптимизаторы запросов не всегда выполняют свою работу так хорошо, как следовало бы. Лучшим вариантом было бы протестировать оба метода и посмотреть, какой из них вам лучше подходит. Ïðàâèëà ïðèìåíåíèÿ çàïðîñîâ UNION Êàê âèäèòå, çàïðîñû UNION î÷åíü ïðîñòû â èñïîëüçîâàíèè. Íî ñóùåñòâóåò íåñêîëüêî ïðàâèë, ÷åòêî óêàçûâàþùèõ, ÷òî èìåííî ìîæåò áûòü îáúåäèíåíî. Çàïðîñ UNION äîëæåí âêëþ÷àòü äâà èëè áîëåå îïåðàòîðîâ SELECT, îòäåëåííûõ îäèí îò äðóãîãî êëþ÷åâûì ñëîâîì UNION (òàêèì îáðàçîì, åñëè â çàïðîñå èñïîëüçóåòñÿ ÷åòûðå îïåðàòîðà SELECT, äîëæíî áûòü èñïîëüçîâàíî òðè êëþ÷åâûõ ñëîâà UNION). Êàæäûé çàïðîñ â îïåðàòîðå UNION äîëæåí ñîäåðæàòü îäíè è òå æå ñòîëáöû, âûðàæåíèÿ èëè ñòàòèñòè÷åñêèå ôóíêöèè (êðîìå òîãî, ñòîëáöû äîëæíû áûòü ïåðå÷èñëåíû â îäíîì è òîì æå ïîðÿäêå). Òèïû äàííûõ ñòîëáöîâ äîëæíû áûòü ñîâìåñòèìûìè. Îíè íå îáÿçàòåëüíî äîëæíû áûòü îäíîãî òèïà, íî îíè äîëæíû áûòü òîãî òèïà, êîòîðûé ÑÓÁÄ ñìîæåò îäíîçíà÷íî ïðåîáðàçîâàòü (íàïðèìåð, ýòî ìîãóò áûòü ðàçëè÷íûå ÷èñëîâûå òèïû äàííûõ èëè ðàçëè÷íûå òèïû äàòû). Ïðè ñîáëþäåíèè ýòèõ îñíîâíûõ ïðàâèë è îãðàíè÷åíèé, çàïðîñû íà ñîåäèíåíèå ìîæíî èñïîëüçîâàòü äëÿ ðåøåíèÿ ëþáûõ çàäà÷ ïî âîçâðàùåíèþ äàííûõ. 150 Урок 14 Âêëþ÷åíèå èëè èñêëþ÷åíèå ïîâòîðÿþùèõñÿ ñòðîê Âîçâðàòèìñÿ ê îäíîìó èç ïðåäûäóùèõ ðàçäåëîâ “Èñïîëüçîâàíèå îïåðàòîðà UNION” è ðàññìîòðèì èñïîëüçîâàííûå â íåì ïðîñòûå îïåðàòîðû SELECT. Âû ìîæåòå çàìåòèòü, ÷òî, êîãäà îíè âûïîëíÿþòñÿ îòäåëüíî, ïåðâûé îïåðàòîð SELECT âîçâðàùàåò òðè ñòðîêè, âòîðîé — äâå. Îäíàêî êîãäà ýòè äâà îïåðàòîðà SELECT êîìáèíèðóþòñÿ ñ UNION, âîçâðàùàþòñÿ òîëüêî ÷åòûðå ñòðîêè, à íå ïÿòü. Çàïðîñ UNION àâòîìàòè÷åñêè óäàëÿåò âñå ïîâòîðÿþùèåñÿ ñòðîêè èç íàáîðà ðåçóëüòàòîâ çàïðîñà (èíûìè ñëîâàìè, îí âåäåò ñåáÿ òî÷íî òàê æå, êàê âåëè áû ñåáÿ íåñêîëüêî ïðåäëîæåíèé WHERE â îäíîì îïåðàòîðå SELECT). Ïîýòîìó çäåñü ïðèñóòñòâóåò çàïèñü î êëèåíòå Fun4All èç øòàòà Èíäèàíà — ýòà ñòðîêà áûëà âîçâðàùåíà îáîèìè îïåðàòîðàìè SELECT. Êîãäà æå èñïîëüçîâàëñÿ çàïðîñ UNION, ïîâòîðÿþùàÿñÿ ñòðîêà áûëà óäàëåíà. Òàêîâî ïîâåäåíèå çàïðîñà UNION ïî óìîë÷àíèþ, íî ïðè æåëàíèè âû ìîæåòå èçìåíèòü åãî. Åñëè áû òðåáîâàëîñü, ÷òîáû âîçâðàùàëèñü âñå âõîæäåíèÿ ñîîòâåòñòâèé, âàì ñëåäîâàëî áû èñïîëüçîâàòü UNION ALL âìåñòî îïåðàòîðà UNION. Ðàññìîòðèì ñëåäóþùèé ïðèìåð: ВВОД SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_state IN ('IL','IN','MI') UNION ALL SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_name = 'Fun4All'; ВЫВОД cust_name ----------Village Toys Fun4All The Toy Fun4All Fun4All cust_contact -----------John Smith Jim Jones Store Kim Howard Jim Jones Denise L.Stephens cust_email [email protected] [email protected] NULL [email protected] [email protected] Комбинированные запросы 151 Анализ Ïðè èñïîëüçîâàíèè çàïðîñà UNION ALL ÑÓÁÄ íå óäàëÿåò äóáëèêàòû. Ïîýòîìó â ïðåäûäóùåì ïðèìåðå âîçâðàùåíî ïÿòü ñòðîê, îäíà èç íèõ ïîâòîðÿåòñÿ äâàæäû. UNION или WHERE В начале этого урока мы говорили, что оператор UNION выполняет то же самое, что и несколько условий WHERE. Оператор UNION ALL является формой запроса UNION, которая делает то, что не способны выполнить предложения WHERE. Если вы хотите получить все вхождения соответствий для каждого условия (включая дубликаты), вам следует использовать оператор UNION ALL, а не WHERE. Ñîðòèðîâêà ðåçóëüòàòîâ êîìáèíèðîâàííûõ çàïðîñîâ Ðåçóëüòàò ïðèìåíåíèÿ îïåðàòîðà SELECT ñîðòèðóåòñÿ ñ ïîìîùüþ ïðåäëîæåíèÿ ORDER BY. Ïðè êîìáèíèðîâàíèè çàïðîñîâ ïîñðåäñòâîì UNION òîëüêî îäíî ïðåäëîæåíèå ORDER ìîæåò áûòü èñïîëüçîâàíî, è îíî äîëæíî ïîÿâèòüñÿ ïîñëå çàêëþ÷èòåëüíîãî îïåðàòîðà SELECT. Ïðàêòè÷åñêè íå èìååò ñìûñëà ñîðòèðîâàòü ÷àñòü íàáîðà ðåçóëüòàòîâ îäíèì ñïîñîáîì, à ÷àñòü — äðóãèì, ïîýòîìó íåñêîëüêî ïðåäëîæåíèé ORDER BY ïðèìåíÿòü íå ðàçðåøàåòñÿ.  ñëåäóþùåì ïðèìåðå ñîðòèðóþòñÿ ðåçóëüòàòû, ïîëó÷åííûå ïðåäûäóùèì çàïðîñîì UNION: ВВОД SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_state IN ('IL','IN','MI') UNION SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_name = 'Fun4All' ORDER BY cust_name, cust_contact; 152 Урок 14 ВЫВОД cust_name ----------Fun4All Fun4All The Toy Store Village Toys cust_contact -----------Denise L.Stephens Jim Jones Kim Howard John Smith cust_email [email protected] [email protected] NULL [email protected] Анализ Ýòîò çàïðîñ UNION èñïîëüçóåò îäíî ïðåäëîæåíèå ORDER BY ïîñëå çàêëþ÷èòåëüíîãî îïåðàòîðà SELECT. Íåñìîòðÿ íà òî ÷òî ORDER BY ÿâëÿåòñÿ ÷àñòüþ òîëüêî ïîñëåäíåãî îïåðàòîðà SELECT, íà ñàìîì äåëå ÑÓÁÄ áóäåò èñïîëüçîâàòü åãî äëÿ ñîðòèðîâêè âñåõ ðåçóëüòàòîâ, âîçâðàùåííûõ âñåìè îïåðàòîðàìè SELECT. Другие типы запроса на соединение Некоторые СУБД поддерживают два дополнительных запроса типа UNION. Оператор EXCEPT (иногда называемый MINUS) может быть использован только для чтения строк, которые существуют в первой таблице, но не во второй, а оператор INTERSECT можно использовать для чтения строк, которые имеются в обеих таблицах. Однако на практике такие запросы UNION используются редко, поскольку те же самые результаты могут быть получены посредством объединений. Ðåçþìå  ýòîì óðîêå âû óçíàëè, êàê ìîæíî êîìáèíèðîâàòü çàïðîñû SELECT ïîñðåäñòâîì îïåðàòîðà UNION. Èñïîëüçóÿ îïåðàòîð UNION, âû ìîæåòå âåðíóòü ðåçóëüòàòû íåñêîëüêèõ çàïðîñîâ â âèäå îäíîãî êîìáèíèðîâàííîãî çàïðîñà, âêëþ÷àþùåãî èëè èñêëþ÷àþùåãî äóáëèêàòû. Çà ñ÷åò èñïîëüçîâàíèÿ îïåðàòîðà UNION ìîæíî çíà÷èòåëüíî óïðîñòèòü ñëîæíûå ïðåäëîæåíèÿ WHERE è îäíîâðåìåííî âûáèðàòü äàííûå èç ìíîãèõ òàáëèö.