
Лабораторна робота №2
ТЕМА РОБОТИ: Робота з оператором SELECT в одній таблиці.
МЕТА РОБОТИ: Навчити студентів витягати інформацію з таблиць за допомогою оператора SELECT
Теоретичні відомості
Про пропозицію SELECT
Всі запити на одержання практично будь-якої кількості даних з однієї або декількох таблиць виконуються за допомогою єдиної пропозиції SELECT. У загальному випадку результатом реалізації пропозиції SELECT є інша таблиця. До цієї нового (робочої) таблиці може бути знову застосована операція SELECT і т.д., тобто такі операції можуть бути вкладені друг у друга. Становить історичний інтерес той факт, що саме можливість включення однієї пропозиції SELECT усередину іншого послужила мотивуванням використання прикметника "структуризований" у назві мови SQL.
Пропозиція SELECT може використатися як:
-
самостійна команда на одержання й висновок рядків таблиці, сформованої зі стовпців і рядків однієї або декількох таблиць (подань);
-
елемент WHERE- або HAVING-умови (скорочений варіант пропозиції, називана "вкладений запит");
-
фраза вибору в командах CREATE VIEW, DECLARE CURSOR або INSERT;
-
засіб присвоєння глобальним змінним значень із рядків сформованої таблиці (INTO-фраза).
У синтаксичних конструкціях оператора SELECT використаються наступні позначення:
-
зірочка (*) для позначення "всі" - уживається у звичайному для програмування змісті, тобто "всі випадки, що задовольняють визначенню";
-
квадратні дужки ([]) - означають, що конструкції, укладені в ці дужки, є необов'язковими (тобто можуть бути опущені);
-
фігурні дужки ({}) - означають, що конструкції, укладені в ці дужки, повинні розглядатися як цілі синтаксичні одиниці, тобто вони дозволяють уточнити порядок розбору синтаксичних конструкцій, заміняючи звичайні дужки, використовувані в синтаксисі SQL;
-
багатокрапковість (...) - вказує на те, що безпосередньо попередня йому синтаксична одиниця факультативно може повторюватися один або більше раз;
-
пряма риса (|) - означає наявність вибору із двох або більше можливостей. Наприклад позначення ASC|DESC указує, можна вибрати один з термінів ASC або DESC; коли ж один з елементів вибору укладений у квадратні дужки, те це означає, що він вибирається за замовчуванням (так, [ASC]|DESC означає, що відсутність всієї цієї конструкції буде сприйматися як вибір ASC);
-
крапка з коми (;) - завершальний елемент пропозицій SQL;
-
кома (,) - використається для поділу елементів списків;
-
пробіли ( ) - можуть уводитися для підвищення наочності між будь-якими синтаксичними конструкціями пропозицій SQL;
-
прописні жирні латинські букви й символи - використаються для написання конструкцій мови SQL і повинні (якщо це спеціально не обговорено) записуватися в точності так, як показано;
-
малі літери - використаються для написання конструкцій, які повинні замінятися конкретними значеннями, обраними користувачем, причому для визначеності окремі слова цих конструкцій зв'язуються між собою символом підкреслення (_);
-
терміни таблиця, стовпець, ... - заміняють (з метою скорочення тексту синтаксичних конструкцій) терміни ім'я_таблиці, ім'я_стовпця, ..., відповідно;
-
термін таблиця - використається для узагальнення таких видів таблиць, як базова_таблиця, подання або псевдонім; тут псевдонім служить для тимчасового (на момент виконання запиту) перейменування й (або) створення робочої копії базової_таблиці (подання).
Пропозиція SELECT (вибрати) має наступний формат:
SELECT[ALL|DISTINCT|TOPn[PERCENT]]WITH TIES select_list
[INTO[new_table_name]]
[FROM{table_name|view_name}[(optimizer_hints)]
[[,{table_name2|view_name2}[(optimizer_hints)]
…,{table_name16|view_name16}[( optimizer_hints)]]]
[WHERE clause]
[GROUP BY clause]
[HAVING clause]
[ORDER BY clause]
[COMPUTE clause]
[FOR BROWSE]
підзапит [UNION [ALL] підзапит] ...
[ORDER BY {[таблиця.]стовпець | номер_елемента_SELECT} [[ASC] | DESC]
[,{[таблиця.]стовпець | номер_елемента_SELECT} [[ASC] | DESC]] ...;
і дозволяє об'єднати (UNION) а потім упорядкувати (ORDER BY) результати вибору даних, отриманих за допомогою декількох "підзапитів". При цьому впорядкування можна робити в порядку зростання - ASC (ASCending) або убування DESC (DESCending), а за замовчуванням приймається ASC.
У цій пропозиції підзапит дозволяє вказати умови для вибору потрібних даних й (якщо потрібно) їхньої обробки.
SELECT
(вибрати) дані із зазначених стовпців й (якщо необхідно) виконати перед висновком їхнє перетворення відповідно до зазначених виражень й (або) функціями
FROM
(з) перерахованих таблиць, у яких розташовані ці стовпці
WHERE
(де) рядка із зазначених таблиць повинні задовольняти зазначеному переліку умов відбору рядків
GROUP BY
(групуючи по) зазначеному переліку стовпців для того, щоб одержати для кожної групи єдине значення, використовуючи у фразі SELECT SQL-функції SUM (сума), COUNT (кількість), MIN (мінімальне значення), MAX (максимальне значення) або AVG (середнє значення)
GROUP BY [таблиця.]стовпець [,[таблиця.]стовпець] ... [HAVING фраза]
GROUP BY ініціює перекомпонування формованої таблиці по групах, кожна з яких має однакове значення в стівпцях, включених у перелік GROUP BY. Далі до цих груп застосовуються агрегирующие функції, зазначені у фразі SELECT, що приводить до заміни всіх значень групи на єдине значення (сума, кількість і т.п.).
За допомогою фрази HAVING (синтаксис якої майже не відрізняється від синтаксису фрази WHERE)
HAVING [NOT] HAVING_умова [[AND|OR][NOT] HAVING_умова]...
можна виключити з результату групи, не задовольняючим заданим умовам:
значення { = | < | < | <= | | = } { значення | ( підзапит )
| SQL_функція }
{значення_1 | SQL_функція_1} [NOT] BETWEEN
{значення_2 | SQL_функція_2} AND {значення_3 | SQL_функція_3}
{значення | SQL_функція} [NOT] IN { ( константа [,константа]... )
| ( підзапит ) }
{значення | SQL_функція} IS [NOT] NULL
[таблиця.]стовпець [NOT] LIKE 'рядок_символів' [ESCAPE 'символ']
EXISTS ( підзапит )
Вибірка без використання фрази WHERE
Проста вибірка
Запит видати назва, статус й адреса постачальників
SELECT Назва, Статус, Адреса
FROM Постачальники;
При необхідності одержання повної інформації про постачальників, можна було б дати запит
SELECT ПС, Назва, Статус, Місто, Адреса, Телефон
FROM Постачальники;
або використати його більше коротку нотацію:
SELECT *
FROM Постачальники;
Тут "зірочка" (*) служить коротким позначенням всіх імен полів у таблиці, зазначеної у фразі FROM. При цьому порядок висновку полів відповідає порядку, у якому ці поля визначалися при створенні таблиці.
Ще один приклад. Видати основу всіх блюд:
SELECT Основа
FROM Блюда;
дає результат, показаний на рис. 2.1,б.
а) |
б) |
в) |
||
Назва |
Статус |
Адреса |
Основа |
Основа |
Овочі |
Кава |
|||
М'ясо |
Крупу |
|||
СИТНИЙ |
Ринок |
Сітнинская, 3 |
Овочі |
Молоко |
ПОРТОС |
Кооператив |
Садова, 27 |
Риба |
М'ясо |
ШУШАРЫ |
Радгосп |
Нова, 17 |
Риба |
Овочі |
ТУЛЬСЬКИЙ |
Універсам |
Тульська, 3 |
М'ясо |
Риба |
УРОЖАЙ |
Коопторг |
Піщана, 19 |
Молоко |
Фрукти |
ЛІТО |
Агрофірма |
Пулковске ш.,8 |
Молоко |
Яйця |
ОГІРОК |
Ферма |
Укмерге, 15 |
|
|
КОРЮШКА |
Кооператив |
Нарвске ш., 64 |
Кава |
Рис. 2.1. Приклади простої вибірки
Виключення дублікатів
У попередньому прикладі був виданий правильний, але не зовсім удалий перелік основних продуктів: з нього не були виключені дублікати. Для виключення дублікатів й одночасного впорядкування переліку необхідно доповнити запит ключовим словом DISTINCT (різний, різні), як показано в наступному прикладі:
SELECT DISTINCT Основа
FROM Блюда;
Результат наведений на рис. 2.1,в.
Вибірка значень, що обчислюють
Із синтаксису фрази SELECT видно, що в ній може втримуватися не тільки перелік стовпців таблиці або символ *, але й вираження.
Наприклад, якщо потрібно одержати значення калорійності всіх продуктів, то можна врахувати, що при окислюванні 1 м вуглеводів або білків в організмі звільняється в середньому 4.1 ккал, а при окислюванні 1 м жирів - 9.3 ккал, і видати запит:
SELECT Продукт, ((Білки+Углев)*4.1+Жири*9.3)
FROM Продукти;
результат якого наведений на рис. 2.2,а.
а) |
б) |
в) |
||||
Продукт |
|
Продукт |
|
Продукт |
|
|
Яловичина |
1928.1 |
Яловичина |
Калорій = |
1928.1 |
Зелень |
118.9 |
Судак |
1523. |
Судак |
Калорій = |
1523. |
Помідори |
196.8 |
Масло |
8287.5 |
Масло |
Калорій = |
8287.5 |
Морква |
349.6 |
Майонез |
6464.7 |
Майонез |
Калорій = |
6464.7 |
Лук |
459.2 |
Яйця |
1618.9 |
Яйця |
Калорій = |
1618.9 |
Яблука |
479.7 |
Сметана |
3011.4 |
Сметана |
Калорій = |
3011.4 |
Молоко |
605.1 |
Молоко |
605.1 |
Молоко |
Калорій = |
605.1 |
Кава |
892.4 |
Сир |
1575. |
Сир |
Калорій = |
1575. |
Судак |
1523. |
Морква |
349.6 |
Морква |
Калорій = |
349.6 |
Сир |
1575. |
Лук |
459.2 |
Лук |
Калорій = |
459.2 |
Яйця |
1618.9 |
Помідори |
196.8 |
Помідори |
Калорій = |
196.8 |
Яловичина |
1928.1 |
Зелень |
118.9 |
Зелень |
Калорій = |
118.9 |
Сметана |
3011.4 |
Рис |
3512.1 |
Рис |
Калорій = |
3512.1 |
Рис |
3512.1 |
Борошно |
3556.7 |
Борошно |
Калорій = |
3556.7 |
Борошно |
3556.7 |
Яблука |
479.7 |
Яблука |
Калорій = |
479.7 |
Цукор |
4091.8 |
Цукор |
4091.8 |
Цукор |
Калорій = |
4091.8 |
Майонез |
6464.7 |
Кава |
892.4 |
Кава |
Калорій = |
892.4 |
Масло |
8287.5 |
Рис.2.2. Приклади запитів з обчислювальними полями
Фраза SELECT може включати не тільки вираження, але й окремі числові або текстові константи. Слід зазначити, що текстові константи повинні полягати в апострофи ('). На рис. 2.2,б наведений результат запиту:
SELECT Продукт, 'Калорій =', ((Білки+Углев)*4.1+Жири *9.3)
FROM Продукти;
А що відбудеться, якщо який-небудь член вираження не визначений, тобто має значення NULL й яким образом з'явилося таке значення?
Якщо при завантаженні рядків таблиці в який-небудь із рядків, що вводять, відсутнє значення для якого-небудь стовпця, то СУБД уведе в таке поле NULL-значення. NULL-значення "придумане" для того, щоб представити єдиним образом "невідомі значення" для будь-яких типів даних. Дійсно, тому що при уведенні даних у стовпець або їхню зміну СУБД забороняє уведення значень не відповідному опису даних цього стовпця, те, наприклад, не можна використати пробіл для відсутнього значення числа. Не можна для цих цілей використати й нуль: немає місяця або дня тижня рівного нулю, та й для чисел нуль не може розглядатися як невідоме значення в одному місці і як відоме - в іншому. При висновку ж NULL-значення на екран або друкувальний пристрій його код відтворюється яким-небудь спеціально заданим символом або набором символів: наприклад, пробілом (якщо його не можна переплутати з текстовим значенням пробілу) або сполученням -0-.
За допомогою спеціальної команди можна встановити в СУБД один з режимів подання NULL-значень при виконанні числових розрахунків: заборона або дозвіл заміни NULL-значення нулем. У першому випадку будь-яке арифметичне вираження, що містить невизначений операнд, буде також мати невизначене значення. У другому випадку результат обчислень буде мати чисельне значення (якщо це значення попадає в діапазон подання відповідного типу даних).
Наприклад, при виконанні запиту
SELECT ПР, Ціна, ДО_в, (Ціна * ДО_в)
FROM Поставки;
і різних "настроюваннях" СУБД можуть бути отримані різні результати:
ПР |
Ціна |
ДО_в |
(Ціна*ДО_в) |
ПР |
Ціна |
ДО_в |
(Ціна*ДО_в) |
9 |
-0- |
-0- |
-0- |
9 |
-0- |
-0- |
0. |
11 |
1.5 |
50 |
75. |
11 |
1.5 |
50 |
75. |
12 |
3. |
10 |
30. |
12 |
3. |
10 |
30. |
15 |
2. |
170 |
340. |
15 |
2. |
170 |
340. |
Рис.2.3. Приклади запитів з використанням NULL-значень
Вибірка c використанням фрази WHERE
Використання операторів порівняння
У синтаксисі фрази WHERE показано, що для відбору потрібних рядків таблиці можна використати оператори порівняння = (дорівнює), < (не дорівнює), < (менше), <= (менше або дорівнює), (більше), = (більше або дорівнює), які можуть випереджатися оператором NOT, створюючи, наприклад, відносини "не менше" й "не більше".
Так, для одержання переліку продуктів, що практично не містять вуглеводів, можна сформувати запит
SELECT Продукт, Білки, Жири, Углев, K, Ca, Na, B2, PP, C
FROM Продукти
WHERE Углев = 0;
і одержати:
Продукт |
Білки |
Жири |
Углев |
K |
Ca |
Na |
B2 |
PP |
C |
Яловичина |
189. |
124. |
0. |
3150 |
90 |
600 |
1.5 |
28. |
0 |
Судак |
190. |
80. |
0. |
1870 |
2700 |
1.1 |
10. |
30 |
|
Можливість використання декількох умов, з'єднаних логічними операторами AND, OR, AND NOT й OR NOT, дозволяє здійснити більше детальний відбір рядків. Так, для одержання переліку продуктів, що практично не містять вуглеводів і натрію, можна сформувати запит:
SELECT Продукт, Білки, Жири, Углев, K, Ca, Na, B2, PP, C
FROM Продукти
WHERE Углев = 0 AND Na = 0;
Результат запиту має вигляд
Продукт |
Білки |
Жири |
Углев |
K |
Ca |
Na |
B2 |
PP |
C |
Судак |
190. |
80. |
0. |
1870 |
270 |
0 |
1.1 |
10. |
30 |
Додамо до цього запиту ще одна умова
SELECT Продукт, Білки, Жири, Углев, K, Ca, Na, B2, PP, C
FROM Продукти
WHERE Углев = 0 AND Na = 0 AND Продукт <> 'Судак';
і одержимо на екрані повідомлення "No rows exist or satisfy the specified clause" або аналогічне (залежно від смаків розроблювачів різних СУБД), що інформує про відсутність рядків, що задовольняють заданому(ым) умові(ям).
Використання BETWEEN
За допомогою BETWEEN ... AND ... (перебуває в інтервалі від ... до ...) можна відібрати рядка, у яких значення якого-небудь стовпця перебувають у заданому діапазоні.
Наприклад, видати перелік продуктів, у яких значення змісту білка перебуває в діапазоні від 10 до 50:
|
Результат: |
|
SELECT Продукт, Білки FROM Продукти WHERE Білки BETWEEN 10 AND 50; |
|
|
Продукт |
Білки |
|
Майонез |
31. |
|
Сметана |
26. |
|
Молоко |
28. |
|
Морква |
13. |
|
Лук |
17. |
Можна задати й NOT BETWEEN (не належить діапазону між), наприклад:
|
Результат: |
|
|
SELECT Продукт, Білки, Жири FROM Продукти WHERE Білки NOT BETWEEN 10 AND 50 AND Жири > 100; |
|
|
|
Продукт |
Білки |
Жири |
|
Яловичина |
189. |
124. |
|
Масло |
60. |
825. |
|
Яйця |
127. |
115. |
|
BETWEEN особливо зручний при роботі з даними, що задають інтервалами, початок і кінець яких розташований у різних стовпцях.
Для приклада скористаємося таблицею "мінімальних окладів" (табл. 2.1), величина яких безпосередньо зв'язана зі студентською стипендією. У цій таблиці для поточного значення мінімального окладу встановлена позамежна дата закінчення 9 вересня 9999 року.
Таблиця 2.1
Мінімальні оклади
<div align="center">
Миноклад |
Початок |
Кінець |
2250 |
01-01-1993 |
31-03-1993 |
4275 |
01-04-1993 |
30-06-1993 |
7740 |
01-07-1993 |
30-11-1993 |
14620 |
01-12-1993 |
30-06-1994 |
20500 |
01-07-1994 |
09-09-9999 |
</div>
Якщо, наприклад, треба було довідатися, які зміни мінімальних окладів вироблялися в 1993/94 навчальному році, то можна видати запит
SELECT Початок, Миноклад
FROM Миноклады
WHERE Початок BETWEEN '1-9-1993' AND '31-8-1994'
і одержати результат:
Початок |
Миноклад |
01-12-1993 |
14620 |
01-07-1994 |
20500 |
Відзначимо, що при формуванні запитів значення дат варто містити в апострофи, щоб СУБД не плутала їх з вираженнями й не намагалася віднімати з 31 значення 8, а потім 1994.
Для виявлення всіх значень мінімальних окладів, які існували в 1993/94 навчальному році, можна сформувати запит
SELECT *
FROM Миноклады
WHERE Початок BETWEEN '1-9-1993' AND '31-8-1994'
OR Кінець BETWEEN '1-9-1993' AND '31-8-1994'
Миноклад |
Початок |
Кінець |
7740 |
01/07/1993 |
30/11/1993 |
14620 |
01/12/1993 |
30/06/1994 |
20500 |
01/07/1994 |
09/09/9999 |
Нарешті, для одержання мінімального окладу на 15-5-1994:
|
Результат: |
|
SELECT Миноклад FROM Миноклады WHERE '15-05-1994' BETWEEN Початок AND Кінець |
|
|
Миноклад |
|
|
14620 |
|
Використання IN
Видати відомості про блюда на основі яєць, крупи й овочів
SELECT *
FROM Блюда
WHERE Основа IN (Яйця Крупу Овочі);
Результат:
<div align="center">
БЛ |
Блюдо |
В |
Основа |
Вихід |
Праця |
1 |
Салат літній |
З |
Овочі |
200. |
3 |
3 |
Салат вітамінний |
З |
Овочі |
200. |
4 |
16 |
Драчена |
Г |
Яйця |
180. |
4 |
17 |
Морква з рисом |
Г |
Овочі |
260. |
3 |
19 |
Омлет з луком |
Г |
Яйця |
200. |
5 |
20 |
Каша рисова |
Г |
Крупу |
210. |
4 |
21 |
Пудинг рисовий |
Г |
Крупу |
160. |
6 |
23 |
Помідори з луком |
Г |
Овочі |
260. |
4 |
</div>
Розглянута форма IN є в дійсності просто коротким записом послідовності окремих порівнянь, з'єднаних операторами OR. Попередня пропозиція еквівалентно такому:
SELECT *
FROM Блюда
WHERE Основа=Яйця OR Основа=Крупу OR Основа=Овочі;
Можна задати й NOT IN (не належить), а також можливість використання IN (NOT IN) з підзапитом.
Використання LIKE
Видати перелік салатів
|
Результат: |
|
SELECT Бл FROM Блюдо WHERE Бл LIKE ‘Салат%’ |
|
|
Блюдо |
|
|
Салат літній |
|
|
Салат м'ясний |
|
|
Салат вітамінний |
|
|
|
Салат рибний |
|
Звичайна форма "ім'я_стовпця LIKE текстова_константа" для стовпця текстового типу дозволяє відшукати всі значення зазначеного стовпця, що відповідають зразку, заданому "текстової_константою". Символи цієї константи інтерпретуються в такий спосіб:
-
символ _ (підкреслення) - заміняє будь-який одиночний символ,
-
символ % (відсоток) - заміняє будь-яку послідовність із N символів (де N може бути нулем),
-
всі інші символи означають просто самі себе.
Отже, у наведеному прикладі SELECT буде здійснювати вибірку записів з таблиці Блюда, для яких значення в стовпці Блюдо починається сполученням 'Салат' і містить будь-яку послідовність із нуля або більше символів, що випливають за сполученням 'Салат'. Якби серед блюд були "Цибульний салат", "Фруктовий салат" і т.п., то вони не були б знайдені. Для їхнього відшукання треба змінити фразу WHERE:
WHERE Блюдо LIKE '%салат%'
або при відсутності розходжень між малими й більшими буквами (таке настроювання допускають деякі СУБД):
WHERE Блюдо LIKE '%Салат%'
Це дозволить відшукати всі салати.
Залучення невизначеного значення (NULL-значення)
Якщо при завантаженні даних не уведене значення в яке-небудь поле таблиці, то СУБД помістить у нього NULL-значення. Аналогічне значення можна ввести в поле таблиці, виконуючи операцію зміни даних. Так, при відсутності відомостей про наявність у постачальників судака й моркви в стовпці Ціна й ДО_у відповідних рядків таблиці Поставки вводиться NULL і там буде зберігатися код NULL-значення, а не 0, 0. або пробіл. (Відзначимо, що в роздруківці таблиці Поставки у цих місцях розташований пробіл, установлений у СУБД для подання NULL-значення при висновку на печатку).
У цьому випадку для виявлення назв продуктів, відсутніх у коморі, шеф-кухар може дати запит
|
Результат: |
ПР |
SELECT DISTINCT ПР FROM Наявність WHERE ДО_в IS NULL; |
2 9 |
Природно, що для виявлення продуктів, що існують у коморі, варто дати запит
SELECT DISTINCT ПР
FROM Наявність
WHERE ДО_в IS NOT NULL;
Використання умов
стовпець IS NULL і стовпець IS NOT NULL
замість, наприклад,
стовпець = NULL і стовпець < NULL
пов'язане з тим, що ніщо - і навіть саме NULL-значення - не вважається рівним іншому NULL-значенню. (Незважаючи на це, два невизначених значення розглядаються, однак, як дублікати один одного при виключенні дублікатів, і пропозиція SELECT DISTINCT дасть у результаті не більше одного NULL-значення.)
Вибірка з упорядкуванням
Найпростіший варіант - упорядкування рядків результату за значенням одного зі стовпців із вказівкою порядку сортування або без такої вказівки. (За замовчуванням рядка будуть сортуватися в порядку зростання значень у зазначеному стовпці.)
Наприклад, видати перелік продуктів і зміст у них основних речовин у порядку убування змісту білка
|
Результат: |
|
|||||
SELECT Продукт, Білки, Жири, Углев FROM Продукти ORDER BY Білки DESC; |
Продукт |
Білки |
Жири |
Углев |
|
|
|
Судак |
190. |
80. |
0. |
||||
Яловичина |
189. |
124. |
0. |
||||
Сир |
167. |
90. |
13. |
||||
Яйця |
127. |
115. |
7. |
||||
Кава |
127. |
36. |
9. |
||||
Борошно |
106. |
13. |
732. |
||||
. . . |
|||||||
|
|
|
|
|
|||
|
|
|
|
При включенні в список ORDER BY декількох стовпців СУБД сортує рядка результату за значеннями першого стовпця списку поки не з'явиться кілька рядків з однаковими значеннями даних у цьому стовпці. Такі рядки сортуються за значеннями наступного стовпця зі списку ORDER BY і т.д.
Наприклад, видати вміст таблиці Блюда, відсортувавши її рядка по видах блюд й основі:
|
Результат: |
||||||||
SELECT * FROM Блюда ORDER BY В Основа; |
БЛ |
Блюдо |
В |
Основа |
Вихід |
Праця |
|
|
|
21 |
Пудинг рисовий |
Г |
Крупу |
160. |
6 |
||||
20 |
Каша рисова |
Г |
Крупу |
210. |
4 |
||||
18 |
Сирники |
Г |
Молоко |
220. |
4 |
||||
. . . |
|||||||||
16 |
Драчена |
Г |
Яйця |
180. |
4 |
||||
28 |
Крем сирний |
Д |
Молоко |
160. |
4 |
||||
. . . |
|||||||||
26 |
Яблука печені |
Д |
Фрукти |
160. |
3 |
||||
7 |
Сметана |
З |
Молоко |
140. |
1 |
||||
8 |
Сир |
З |
Молоко |
140. |
2 |
||||
2 |
Салат м'ясний |
З |
М'ясо |
200. |
4 |
||||
6 |
М'ясо з гарніром |
З |
М'ясо |
250. |
3 |
||||
1 |
Салат літній |
З |
Овочі |
200. |
3 |
||||
. . . |
|||||||||
|
|
|
|
|
|||||
|
|
|
|
Крім того, у список ORDER BY можна включати не тільки ім'я стовпця, а його порядкову позицію в переліку SELECT. Завдяки цьому можливо впорядкування результатів на основі стовпців, що обчислюють, що не мають імен.
Наприклад, запит
SELECT Продукт, ((Білки+Углев)*4.1+Жири*9.3)
FROM Продукти
ORDER BY 2;
дозволить одержати список продуктів, показаний на рис. 2.2,в - з по зростанню значень калорійності список рис. 2.2а.
Агрегування даних
SQL-функції
В SQL існує ряд спеціальних стандартних функцій (SQL-функцій). Крім спеціального випадку COUNT(*) кожна із цих функцій оперує сукупністю значень стовпця деякої таблиці й створює єдине значення, обумовлене так:
COUNT
- число значень у стовпці,
SUM
- сума значень у стовпці,
AVG
- середнє значення в стовпці,
MAX
- найбільше значення в стовпці,
MIN
- найменше значення в стовпці.
Для функцій SUM й AVG розглянутий стовпець повинен містити числові значення.
Слід зазначити, що тут стовпець - це стовпець віртуальної таблиці, у якій можуть утримуватися дані не тільки зі стовпця базової таблиці, але й дані, отримані шляхом функціонального перетворення й (або) зв'язування символами арифметичних операцій значень із одного або декількох стовпців. При цьому вираження, що визначає стовпець такої таблиці, може бути як завгодно складним, але не повинне містити SQL-функцій (вкладеність SQL-функцій не допускається). Однак з SQL-функцій можна становити будь-які вираження.
Аргументу всіх функцій, крім COUNT(*), може передувати ключове слово DISTINCT (різний), що вказує, що надлишкові дублюючі значення повинні бути виключені перед тим, як буде застосовуватися функція. Спеціальна ж функція COUNT(*) служить для підрахунку всіх без винятку рядків у таблиці (включаючи дублікати).
Функції без використання фрази GROUP BY
Якщо не використається фраза GROUP BY, то в перелік елементів_SELECT можна включати лише SQL-функції або вираження, що містять такі функції. Інакше кажучи, не можна мати в списку стовпці, що не є аргументами SQL-функцій.
Наприклад, видати дані про масу лука (ПР=10), проданого постачальниками, і вказати кількість цих постачальників:
|
Результат: |
|
SELECT SUM(ДО_в),COUNT(ДО_в) FROM Поставки WHERE ПР = 10; |
|
|
SUM(ДО_в) |
COUNT(ДО_в) |
|
220 |
2 |
Якби для висновку в результат ще й номера продукту був сформований запит
SELECT ПР,SUM(ДО_в),COUNT(ДО_в)
FROM Поставки
WHERE ПР = 10;
то було б отримане повідомлення про помилку. Це пов'язане з тим, що SQL-функція створює єдине значення з безлічі значень стовпця-аргументу, а для "вільного" стовпця повинне бути видане вся безліч його значень. Без спеціальної вказівки (воно задається фразою GROUP BY) SQL не буде з'ясовувати, однакові значення цієї безлічі (як у даному прикладі, де ПР=10) або різні (як було б при відсутності WHERE фрази). Тому подібний запит відкидається системою.
Правда, ніхто не забороняє дати запит
SELECT 'У лука =',SUM(ДО_в),COUNT(ДО_в)
FROM Поставки
WHERE ПР = 10;
Результат: |
||
'У лука =' |
SUM(ДО_в) |
COUNT(ДО_в) |
У лука = |
220 |
2 |
|
|
|
Відзначимо також, що в аргументі-стовпці-аргументі перед застосуванням будь-якої функції, крім COUNT(*), виключаються всі невизначені значення. Якщо виявляється, що аргумент - порожня безліч, функція COUNT приймає значення 0, а інші - NULL.
Наприклад, для одержання суми цін, середньої ціни, кількості продуктів, що поставляють, і кількості різних цін продуктів, проданих коопторгом УРОЖАЙ (ПС=5), а також для одержання кількості продуктів, які можуть поставлятися цим коопторгом, можна дати запит
SELECT SUM(Ціна),AVG(Ціна),COUNT(Ціна),
COUNT(DISTINCT Ціна),COUNT(*)
FROM Поставки
WHERE ПС = 5;
і одержати
SUM(Ціна) |
AVG(Ціна) |
COUNT(Ціна) |
COUNT(DISTINCT Ціна) |
COUNT (*) |
6.2 |
1.24 |
5 |
4 |
7 |
В іншому прикладі, де треба довідатися "Скільки поставлено моркви й скільки постачальників її поставляють?":
SELECT SUM(ДО_в),COUNT(ДО_в)
FROM Поставки
WHER ПР = 2;
буде отримана відповідь:
SUM(ДО_в) |
COUNT (ДО_в) |
-0- |
0 |
Нарешті, спробуємо одержати суму маси поставленого лука з його середньою ціною ("Чоботи з яєчнею"):
|
Результат: |
SELECT (SUM(ДО_в) +AVG(Ціна)) FROM Поставки WHERE ПР = 10; |
|
SUM(ДО_в)+AVG(Ціна) |
|
220.6 |
Фраза GROUP BY
Ми показали, як можна обчислити масу певного продукту, що поставляє постачальниками. Припустимо, що тепер потрібно обчислити загальну масу кожного із продуктів, що поставляють у цей час постачальниками. Це можна легко зробити за допомогою пропозиції
SELECT ПР, SUM(ДО_в)
FROM Поставки
GROUP BY ПР;
Результат показаний на рис. 2.4,а.
<div align="center">
</div>
А) |
Б) |
В) |
|
||||||
ПР |
|
ПС |
ПР |
Ціна |
ДО_в |
|
ПР |
||
9 |
0 |
1 |
9 |
-0- |
-0- |
|
1 |
0 |
|
11 |
150 |
3 |
9 |
-0- |
-0- |
|
2 |
150 |
|
12 |
30 |
5 |
9 |
-0- |
-0- |
|
3 |
30 |
|
15 |
370 |
1 |
11 |
1.50 |
50 |
|
4 |
70 |
|
1 |
370 |
5 |
11 |
-0- |
-0- |
|
5 |
370 |
|
3 |
250 |
6 |
11 |
-0- |
-0- |
|
6 |
250 |
|
5 |
170 |
8 |
11 |
1.00 |
100 |
|
7 |
70 |
|
6 |
220 |
1 |
12 |
3.00 |
10 |
|
8 |
140 |
|
8 |
150 |
3 |
12 |
2.50 |
20 |
|
9 |
150 |
|
7 |
200 |
6 |
12 |
-0- |
-0- |
|
10 |
200 |
|
2 |
0 |
1 |
15 |
2.00 |
170 |
|
11 |
150 |
|
4 |
100 |
3 |
15 |
1.50 |
200 |
|
12 |
30 |
|
13 |
190 |
2 |
1 |
3.60 |
300 |
|
13 |
190 |
|
14 |
70 |
7 |
1 |
4.20 |
70 |
|
14 |
70 |
|
16 |
250 |
2 |
3 |
-0- |
-0- |
|
15 |
370 |
|
17 |
50 |
7 |
3 |
4.00 |
250 |
|
16 |
250 |
|
10 |
220 |
… |
|
17 |
50 |
Рис. 2.4. Ілюстрації до фрази GROUP BY
Фраза GROUP BY (групувати по) ініціює перекомпонування зазначеної в FROM таблиці по групах, кожна з яких має однакові значення в стовпці, зазначеному в GROUP BY. У розглянутому прикладі рядка таблиці Поставки групуються так, що в одній групі втримуються всі рядки для продукту із ПР = 1, в іншій - для продукту із ПР = 2 і т.д. (див. рис. 2.4.б). Далі до кожної групи застосовується фраза SELECT. Кожне вираження в цій фразі повинне приймати єдине значення для групи, тобто воно може бути або значенням стовпця, зазначеного в GROUP BY, або арифметичним вираженням, що включає це значення, або константою, або однієї з Функці-SQL-функцій, що оперує всіма значеннями стовпця в групі й зводить ці значення до єдиного значення (наприклад, до суми).
Відзначимо, що фраза GROUP BY не припускає ORDER BY. Щоб гарантувати впорядкування по ПР результату розглянутого приклада (рис. 2.4,в) варто дати запит
SELECT ПР, SUM(ДО_в)
FROM Поставки
GROUP BY ПР
ORDER BY ПР;
Нарешті, відзначимо, що рядка таблиці можна групувати по будь-якій комбінації її стовпців. Так, по запиті
SELECT Т, БЛ, COUNT(БЛ)
FROM Замовлення
GROUP BY Т, БЛ;
можна довідатися коди й кількість порцій блюд, замовлених відпочиваючого пансіонату (32 чоловік) на кожну із трапез наступного дня:
Т |
БЛ |
COUNT(БЛ) |
1 |
3 |
18 |
1 |
6 |
14 |
1 |
19 |
17 |
1 |
21 |
15 |
... |
Якщо в запиті використаються фрази WHERE й GROUP BY, то рядки, що не задовольняють фразі WHERE, виключаються до виконання групування.
Наприклад, видати для кожного продукту його код і загальний обсяг можливих поставок, з огляду на тимчасову недієздатність постачальника із ПС=2:
SELECT ПР, SUM(ДО_в)
FROM Поставки
WHERE ПС <> 2
GROUP BY ПР;
Використання фрази HAVING
Фраза HAVING (рис.2.4) грає таку ж роль для груп, що й фраза WHERE для рядків: вона використається для виключення груп, точно так само, як WHERE використається для виключення рядків. Ця фраза включається в пропозицію лише при наявності фрази GROUP BY, а вираження в HAVING повинне приймати єдине значення для групи.
Наприклад, видати коди продуктів, що поставляють більш ніж двома постачальниками:
SELECT FROM Поставки GROUP BY ПС HAVING COUNT(*) 2; |
Результат: |
ПР |
9 |
||
11 |
||
12 |
||
|