Типичните заявки във формата на таблицата SELECT * FROM понякога не са достатъчни. Когато данните за заявка не са в една таблица, а в няколко, или когато е необходимо да посочите няколко параметъра за избор наведнъж, ще ви трябват по-сложни заявки.
Тази статия ще обясни как да се изградят такива заявки и ще предостави примери за сложни SQL заявки.
Как изглежда една сложна заявка?
Първо, нека дефинираме условията за съставяне на SQL заявката. По-специално, ще трябва да използвате следните параметри за избор:
- имена на таблиците, от които искате да извлечете данни;
- стойностите на полетата, които трябва да бъдат върнати към оригиналните след извършване на промени в базата данни;
- връзките между таблиците;
- условията за вземане на проби;
- спомагателните критерии за подбор (ограничения, начини за представяне на информация, вид сортиране).
За да разберем по-добре темата, нека разгледаме пример, който използва следните четири прости таблици. Първият ред е името на таблицата, която при сложни заявки действа като външен ключ. Ще разгледаме това подробно по-нататък с пример:
Всяка таблица има редове, свързани с някои други таблици. Ще обясним защо е необходимо допълнително.
Сега нека разгледаме основната SQL заявка:
SELECT * FROM companies WHERE companies_name %STARTSWITH 'P';
% ЗАПОЧВА С предикатът избира редове, започващи с посочения знак/символи.
Резултатът изглежда така:
Сега нека разгледаме сложна SQL заявка:
SELECT
companies.companies_name,
SUM(CASE WHEN call.id IS NOT NULL THEN 1 ELSE 0 END) AS calls,
AVG(ISNULL(DATEDIFF(SECOND, calls.start_time, calls.end_time),0)) AS avgdifference
FROM companies
LEFT JOIN offices ON offices.companies_id = companies.id
LEFT JOIN customers ON offices.id = customers.offices_id
LEFT JOIN calls ON calls.customers_id = customers.id
GROUP BY
companies.id,
companies.companies_name
HAVING AVG(ISNULL(DATEDIFF(SECOND, calls.start_time, calls.end_time),0)) > (SELECT AVG(DATEDIFF(SECOND, calls.start_time, calls.end_time)) FROM calls)
ORDER BY calls DESC, companies.id ASC;
Резултатът е следната таблица:
Таблицата показва фирмите, съответния брой телефонни обаждания и приблизителната им продължителност.
Освен това той изброява само имената на компаниите, при които средната продължителност на разговора е по-голяма от средната продължителност на разговорите в други компании.
Какви са основните правила за създаване на сложна SQL заявка?
Нека се опитаме да създадем многофункционален алгоритъм за съставяне на сложни заявки.
На първо място, трябва да вземете решение за таблиците, състоящи се от данните, които участват в заявката.
Примерът по-горе включва фирмите иобаждания маси. Ако таблиците с необходимите данни не са пряко свързани една с друга, трябва да включите и междинните таблици, които ги свързват.
Поради тази причина свързваме и маси, като например офиси иклиенти , използвайки външни ключове. Следователно всеки резултат от заявката с таблици от този пример винаги ще включва следните редове:
SELECT
...
FROM companies
LEFT JOIN offices ON offices.companies_id = companies.id
LEFT JOIN customers ON offices.id = customers.offices_id
LEFT JOIN calls ON calls.customers_id = customers.id
...;
After that, you must test the correctness of the behavior in the following part of the query:
SELECT * FROM companies
LEFT JOIN offices ON offices.companies_id = companies.id
LEFT JOIN customers ON offices.id = customers.offices_id
LEFT JOIN calls ON calls.customers_id = customers.id;
Комбинирана таблица предлага трите най-важни точки:
- Обърнете внимание на списъка с полета след SELECT. Операцията по четене на данни от обединени таблици изисква да посочите името на таблицата, която ще бъде обединена в име поле.
- Вашата сложна заявка винаги ще има основната таблица (компании ). Повечето полета се четат от него. Приложената таблица в нашия пример използва три таблици – офиси ,клиенти , иобаждания . Името се определя след оператора JOIN.
- Освен да посочите името на втората таблица, не забравяйте да посочите условието за извършване на свързването. Ще обсъдим това условие допълнително.
- Заявката ще покаже таблица с голям брой редове. Не е необходимо да го публикувате тук, тъй като показва междинни резултати. Въпреки това, винаги можете сами да проверите изхода му. Това е много важно, тъй като помага да се избегнат грешки в крайния резултат.
Сега нека разгледаме частта от заявката, която сравнява продължителността на разговорите във всяка компания и между всички компании. Трябва да изчислим средната продължителност на всички разговори. Използвайте следната заявка:
SELECT AVG(DATEDIFF(SECOND, calls.start_time, calls.end_time)) FROM calls
Имайте предвид, че използвахме DATEDIFF функция, която извежда разликата между посочените периоди. В нашия случай средната продължителност на разговора е равна на 335 секунди.
Сега нека добавим към заявката данни за обажданията от всички компании.
SELECT
companies.companies_name,
SUM(CASE WHEN calls.id IS NOT NULL THEN 1 ELSE 0 END) AS calls,
AVG(ISNULL(DATEDIFF(SECOND, calls.start_time, calls.end_time),0)) AS avgdifference
FROM companies
LEFT JOIN offices ON offices.companies_id = companies.id
LEFT JOIN customers ON offices.id = customers.offices_id
LEFT JOIN calls ON calls.customers_id = customers.id
GROUP BY
companies.id,
companies.companies_name
ORDER BY calls DESC, companies.id ASC;
В тази заявка,
- SUM (СЛУЧАЙ, КОГАТО calls.id НЕ Е NULL, ТОГАВА 1 ДРУГА 0 КРАЙ) – за да избегнем ненужни операции, ние обобщаваме само съществуващите обаждания – когато броят на обажданията в една компания не е нула. Това е много важно при големи таблици с възможни нулеви стойности.
- AVG (ISNULL (DATEDIFF (SECOND, calls.start_time, calls.end_time), 0)) – заявката е идентична с AVG заявката по-горе. Тук обаче използваме ISNULL оператор, който заменя NULL с 0. Необходим е за компании, в които изобщо няма обаждания.
Нашите резултати:
Почти сме готови. Таблицата по-горе представя списъка на компаниите, съответния брой обаждания за всяка от тях и средната продължителност на разговорите във всяка от тях.
Единственото, което остава, е да сравните числата от последната колона със средната продължителност на всички обаждания от всички компании (335 секунди).
Ако въведете заявката, която представихме в самото начало, просто добавяте ИМАМ част, ще получите това, от което се нуждаете.
Силно препоръчваме да добавяте коментари на всеки ред, за да не се объркате в бъдеще, когато трябва да коригирате някои съществуващи сложни SQL заявки.
Последни мисли
Въпреки че всяка сложна SQL заявка изисква индивидуален подход, някои препоръки са подходящи за подготовката на повечето такива заявки.
- определете кои таблици ще участват в заявката;
- създайте сложни заявки от по-прости части;
- проверете точността на заявките последователно, на части;
- тествайте точността на заявката си с по-малки таблици;
- напишете подробни коментари на всеки ред, съдържащ операнда, като използвате символите „-“.
Специализираните инструменти правят тази работа много по-лесна. Сред тях бихме препоръчали използването на Query Builder – визуален инструмент, който позволява да се изграждат дори най-сложните заявки много по-бързо във визуален режим. Този инструмент се предлага като самостоятелно решение или като част от многофункционалното dbForge Studio за SQL Server.
Надяваме се, че тази статия ви е помогнала да изясните този конкретен проблем.