Как да мислим в SQL
Автор: Рахим Давлеткалиев
Ако сте като мен, тогава ще се съгласите: SQL е едно от онези неща, които изглеждат лесни на пръв поглед (чете се сякаш е на английски!), но по някаква причина трябва да търсите в Google всяка проста заявка, за да намерите правилния синтаксис.
И тогава започват съединения, агрегиране, подзапитвания и се оказва, че е пълен боклук. Като този:
Буе! Това ще изплаши всеки начинаещ или дори обикновен разработчик, ако види SQL за първи път. Но не всичко е толкова лошо.
Лесно е да запомните какво е интуитивно и с това ръководство се надявам да намаля бариерата за навлизане в SQL за начинаещи, като същевременно предлагам нов поглед върху SQL за по-опитните.
Въпреки че синтаксисът на SQL е почти еднакъв в различните бази данни, тази статия използва PostgreSQL за заявки. Някои примери ще работят в MySQL и други бази данни.
1. Три вълшебни думи
В SQL има много ключови думи, но SELECT, FROM и WHERE присъстват в почти всяка заявка. Малко по-късно ще разберете, че тези три думи представляват най-фундаменталните аспекти на изграждането на заявки към базата данни, а други, по-сложни заявки са само добавки към тях.
2. Нашата база
Нека да разгледаме базата данни, която ще използваме като пример в тази статия:
Имаме библиотека и хора. Има и специална таблица за отчитане на издадените книжки.
3. Проста заявка
Искането ще бъде така:
И резултатът е такъв:
2 | Изгубеният символ |
4 | Ад |
Доста просто. Нека разбием искането, за да разберем какво се случва.
3.1 ОТ - откъде го вземамеданни
Това може да изглежда очевидно сега, но FROM ще бъде много важно по-късно, когато стигнем до обединения и подзаявки.
FROM сочи към таблицата за заявка. Това може да бъде вече съществуваща таблица (както в примера по-горе) или таблица, създадена в движение чрез съединения или подзаявки.
3.2 КЪДЕ - какви данни да се показват
WHERE просто се държи като филтър наредовете, които искаме да изведем. В нашия случай искаме да видим само редове, където стойността в колоната за автор е „Дан Браун“.
3.3 SELECT - как показваме данните
Сега, когато имаме всички колони, от които се нуждаем от таблицата, която ни трябва, трябва да решим как точно да покажем тези данни. В нашия случай се нуждаем само от заглавията на книгите и идентификаторите, така че това ще изберем с SELECT. В същото време можете да преименувате колоната с помощта на AS.
Цялата заявка може да се визуализира с проста диаграма:

4. Връзки (съединявания)
Сега искаме да видим заглавията (не непременно уникални) на всички книги на Дан Браун, които са били заети от библиотеката, и кога тези книги трябва да бъдат върнати:
Изгубеният символ | 2016-03-23 00:00:00 |
Ад | 2016-04-13 00:00:00 |
Изгубеният символ | 2016-04-19 00:00:00 |
В по-голямата си част заявката е подобна на предишната, с изключение на клаузата FROM. Това означава, че изискваме данни от друга таблица. Нямаме достъп нито до таблицата „книги“, нито до таблицата „заеми“. Вместо това се позоваваме на новата таблица, която е създадена чрез свързване на тези две таблици.
заеми ПРИСЪЕДИНЕТЕ СЕ към книги В borrowings.book > - това е, помислете, нова таблица, която е формираначрез комбиниране на всички записи от таблиците "книги" и "заеми", където стойностите на bookid съвпадат. Резултатът от такова сливане ще бъде:
И след това правим заявка към тази таблица по същия начин, както в горния пример. Това означава, че когато се присъединявате към маси, вие трябва да се притеснявате само как да извършите това присъединяване. И тогава заявката става толкова ясна, колкото и при „простата заявка“ от точка 3.
Нека опитаме малко по-сложно съединение с две таблици.
Този път да преминем отдолу нагоре:
Стъпка 1 - откъде получаваме данните? За да получим желания резултат, трябва да обединим таблиците "член" и "книги" с таблицата "заеми". Секцията JOIN ще изглежда така:
Резултатът от връзката можете да видите на линка.
Стъпка 3 - как да покажем данните? Сега, след като данните са получени, трябва само да покажете имената и фамилиите на тези, които са взели книгите:
Супер! Остава само да комбинираме трите компонента и да направим заявката, от която се нуждаем:
Майк | Уилис |
Елън | Хортън |
Елън | Хортън |
Страхотен! Но имената се повтарят (не са уникални). Скоро ще поправим това.
5. Агрегиране
Грубо казано, агрегатите са необходими за преобразуване на множество низове в един. В същото време по време на агрегацията се използва различна логика за различните колони.
Нека продължим с нашия пример, където се появяват дублирани имена. Можете да видите, че Елън Хортън е взела назаем повече от една книга, но това не е най-добрият начин да покажете тази информация. Можете да направите друга заявка:
Което ще ни даде желания резултат:
Майк | Уилис | 1 |
Елън | Хортън | 2 |
Почти всички агрегати идват с клауза GROUP BY. Това нещо превръща таблица, която може да бъде получена чрез заявка, в групи от таблици. Всяка група съответства на уникална стойност (или група от стойности) на колоната, която сме посочили в GROUP BY. В нашия пример ние преобразуваме резултата от предишното упражнение в група низове. Също така правим агрегиране с count, което преобразува множество редове в цяло число (в нашия случай, броя на редовете). След това тази стойност се присвоява на всяка група.
Всеки ред в резултата е резултат от агрегирането на всяка група.
Можете да стигнете до логичното заключение, че всички полета в резултата трябва или да бъдат посочени в GROUP BY, или да се извърши агрегиране върху тях. Тъй като всички други полета могат да се различават едно от друго в различни редове и ако ги изберете с SELECT 'th, тогава не е ясно коя от възможните стойности трябва да се вземе.