Бази даних-20210115T104840Z-001 / Реферат на тему _Современные СУБД_ / Using_MySql,_MS_SQL_Server_and_Oracle(1)
.pdfПример 4: использование функции COUNT в запросе с условием
Решение 2.1.4.b{29}.
Здесь мы расширяем решение{29} задачи 2.1.4.a{29}, добавляя ключевое слово DISTINCT в параметр функции COUNT, что обеспечивает подсчёт неповторяющихся
значений поля sb_book.
MySQL |
Решение 2.1.4.b |
||
1 |
SELECT |
COUNT(DISTINCT `sb_book`) AS `in_use` |
|
2 |
FROM |
`subscriptions` |
|
3 |
WHERE |
`sb_is_active` = 'Y' |
|
|
|
||
MS SQL |
Решение 2.1.4.b |
||
1 |
SELECT |
COUNT(DISTINCT [sb_book]) AS [in_use] |
|
2 |
FROM |
[subscriptions] |
|
3 |
WHERE |
[sb_is_active] = 'Y' |
|
|
|
|
|
Oracle |
|
Решение 2.1.4.b |
|
1 |
SELECT |
COUNT(DISTINCT "sb_book") AS "in_use" |
|
2 |
FROM |
"subscriptions" |
|
3 |
WHERE |
"sb_is_active" = 'Y' |
Задание 2.1.4.TSK.A: показать, сколько всего раз читателям выдавались книги.
Задание 2.1.4.TSK.B: показать, сколько читателей брало книги в библиотеке.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 30/545
Пример 5: использование функций SUM, MIN, MAX, AVG
2.1.5. Пример 5: использование функций SUM, MIN, MAX, AVG
Задача 2.1.5.a{31}: показать общее (сумму), минимальное, максимальное и среднее значение количества экземпляров книг в библиотеке.
Ожидаемый результат 2.1.5.a.
sum |
min |
max |
avg |
33 |
1 |
12 |
4.7143 |
Решение 2.1.5.a{31}.
В такой простой формулировке эта задача решается запросом, в котором достаточно перечислить соответствующие функции, передав им в качестве параметра поле b_quantity (и только в MS SQL Server придётся сделать небольшую доработку).
MySQL Решение 2.1.5.a
1SELECT SUM(`b_quantity`) AS `sum`,
2MIN(`b_quantity`) AS `min`,
3MAX(`b_quantity`) AS `max`,
4AVG(`b_quantity`) AS `avg`
5 FROM `books`
MS SQL Решение 2.1.5.a
1SELECT SUM([b_quantity]) AS [sum],
2MIN([b_quantity]) AS [min],
3MAX([b_quantity]) AS [max],
4AVG(CAST([b_quantity] AS FLOAT)) AS [avg]
5 FROM [books]
Oracle Решение 2.1.5.a
1SELECT SUM("b_quantity") AS "sum",
2MIN("b_quantity") AS "min",
3MAX("b_quantity") AS "max",
4AVG("b_quantity") AS "avg"
5FROM "books"
Обратите внимание на 4-ю строку в запросе 2.1.5.a для MS SQL Server: без приведения функцией CAST значения количества книг к дроби, итоговый результат работы функции AVG будет некорректным (это будет целое число), т.к. MS SQL Server выбирает тип данных результата на основе типа данных входного параметра. Продемонстрируем это.
MS SQL Решение 2.1.5.a (пример запроса с ошибкой)
1SELECT SUM([b_quantity]) AS [sum],
2MIN([b_quantity]) AS [min],
3MAX([b_quantity]) AS [max],
4AVG([b_quantity]) AS [avg]
5FROM [books]
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 31/545
Пример 5: использование функций SUM, MIN, MAX, AVG
Получится:
sum |
min |
max |
avg |
|
33 |
1 |
12 |
4 |
|
|
А должно быть: |
|||
|
|
|
|
|
sum |
min |
max |
avg |
|
33 |
1 |
12 |
4.7143 |
Стоит упомянуть ещё одну опасную ошибку: очень легко забыть, что при вычислении суммы и среднего значения (которое определяется как сумма, поделённая на количество значений) может произойти переполнение разрядной сетки.
Исследование 2.1.5.EXP.A: рассмотрим реакцию различных СУБД на ситуацию переполнения разрядной сетки.
Создадим в БД «Исследование» таблицу overflow с одним числовым целочисленным полем:
dm MySQL |
dm SQLServ er2012 |
dm Oracle |
ov erflow |
ov erflow |
ov erflow |
«column» |
«column» |
«column» |
x: INT |
x: int |
x: NUMBER(10) |
MySQL MS SQL Server Oracle
Рисунок 2.1.g — Таблица overflow во всех трёх СУБД
Поместим в созданную таблицу три максимальных значения для её поля x:
x |
|
x |
|
x |
2147483647 |
|
2147483647 |
|
9999999999 |
2147483647 |
|
2147483647 |
|
9999999999 |
2147483647 |
|
2147483647 |
|
9999999999 |
MySQL |
MS SQL Server |
Oracle |
Теперь выполним для каждой СУБД запросы на получение суммы значений из поля x и среднего значения в поле x:
MySQL Исследование 2.1.5.EXP.A
1-- Запрос 1: SUM
2SELECT SUM(`x`) AS `sum`
3 FROM `overflow`
1-- Запрос 2: AVG
2SELECT AVG(`x`) AS `avg`
3FROM `overflow`
MS SQL Исследование 2.1.5.EXP.A
1-- Запрос 1: SUM
2SELECT SUM([x]) AS [sum]
3 FROM [overflow]
1-- Запрос 2: AVG
2SELECT AVG([x]) AS [avg]
3FROM [overflow]
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 32/545
Пример 5: использование функций SUM, MIN, MAX, AVG
Oracle Исследование 2.1.5.EXP.A
1-- Запрос 1: SUM
2SELECT SUM("x") AS "sum"
3 FROM "overflow"
1-- Запрос 2: AVG
2SELECT AVG("x") AS "avg"
3FROM "overflow"
MySQL и Oracle выполнят запросы 2.1.5.EXP.A и вернут корректные данные, а в MS SQL Server мы получим сообщение об ошибке:
Msg 8115, Level 16, State 2, Line 1. Arithmetic overflow error converting expression to data type int.
Это вполне логично, т.к. при попытке разместить в переменной типа INT трёхкратное максимальное значение типа INT, возникает переполнение разрядной сетки.
MySQL и Oracle менее подвержены этому эффекту, т.к. у них «в запасе» есть DECIMAL и NUMBER, в формате которых и происходит вычисление. Но при достаточном объёме данных там тоже возникает переполнение разрядной сетки.
Особая опасность этой ошибки состоит в том, что на стадии разработки и поверхностного тестирования БД она не проявляется, и лишь со временем, когда у реальных пользователей накопится большой объём данных, в какой-то момент ранее прекрасно работавшие запросы перестают работать.
Исследование 2.1.5.EXP.B. Чтобы больше не возвращаться к особенностям работы агрегирующих функций, рассмотрим их поведение в случае наличия в анализируемом поле NULL-значений, а также в случае пустого набора входных значений.
Используем ранее созданную таблицу table_with_nulls{26}. В ней по-преж- нему находятся следующие данные:
x
1
1
2
NULL
Выполним запросы 2.1.5.EXP.B:
MySQL Исследование 2.1.5.EXP.B
1SELECT SUM(`x`) AS `sum`,
2MIN(`x`) AS `min`,
3MAX(`x`) AS `max`,
4AVG(`x`) AS `avg`
5 FROM `table_with_nulls`
MS SQL Исследование 2.1.5.EXP.B
1SELECT SUM([x]) AS [sum],
2MIN([x]) AS [min],
3MAX([x]) AS [max],
4AVG(CAST([x] AS FLOAT)) AS [avg]
5 FROM [table_with_nulls]
Oracle Исследование 2.1.5.EXP.B
1SELECT SUM("x") AS "sum",
2MIN("x") AS "min",
3MAX("x") AS "max",
4AVG("x") AS "avg"
5FROM "table_with_nulls"
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 33/545
Пример 5: использование функций SUM, MIN, MAX, AVG
Все запросы 2.1.5.EXP.B возвращают почти одинаковый результат (разница только в количестве знаков после запятой в значении функции AVG: у MySQL там четыре знака, у MS SQL Server и Oracle — 14 и 38 знаков соответственно):
sum |
min |
max |
avg |
4 |
1 |
2 |
1.3333 |
Как легко заметить из полученных данных, ни одна из функций не учитывает NULL-значения.
Исследование 2.1.5.EXP.C. Последний эксперимент будет заключаться в применении к выборке такого условия, которому не соответствует ни один ряд: таким образом в выборке окажется пустое множество строк.
MySQL Исследование 2.1.5.EXP.C
1SELECT SUM(`x`) AS `sum`,
2MIN(`x`) AS `min`,
3MAX(`x`) AS `max`,
4AVG(`x`) AS `avg`
5 |
|
FROM |
`table_with_nulls` |
6 |
|
WHERE |
`x` < 0 |
|
|
|
|
MS SQL Исследование 2.1.5.EXP.C
1SELECT SUM([x]) AS [sum],
2MIN([x]) AS [min],
3MAX([x]) AS [max],
4AVG(CAST([x] AS FLOAT)) AS [avg]
|
5 |
|
FROM |
[table_with_nulls] |
|
|
6 |
|
WHERE |
[x] < 0 |
|
|
|
|
|
||
|
Oracle |
|
Исследование 2.1.5.EXP.C |
1SELECT SUM("x") AS "sum",
2MIN("x") AS "min",
3MAX("x") AS "max",
4AVG("x") AS "avg"
5 |
|
FROM |
"table_with_nulls" |
6 |
|
WHERE |
"x" < 0 |
Здесь все три СУБД также работают одинаково, наглядно демонстрируя, что на пустом множестве функции SUM, MIN, MAX, AVG возвращают NULL:
sum |
min |
max |
avg |
NULL |
NULL |
NULL |
NULL |
Также обратите внимание, что при вычислении среднего значения не произошло ошибки деления на ноль.
Логику работы на пустом множестве значений функции COUNT мы уже рассмотрели ранее (см. исследование 2.1.3.EXP.B{28}).
Задание 2.1.5.TSK.A: показать первую и последнюю даты выдачи книги читателю.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 34/545
Пример 6: упорядочивание выборки
2.1.6. Пример 6: упорядочивание выборки
Задача 2.1.6.a{35}: показать все книги в библиотеке в порядке возрастания их года издания.
Задача 2.1.6.b{36}: показать все книги в библиотеке в порядке убывания их года издания.
Ожидаемый результат 2.1.6.a.
b_name |
b_year |
Курс теоретической физики |
1981 |
Евгений Онегин |
1985 |
Сказка о рыбаке и рыбке |
1990 |
Искусство программирования |
1993 |
Язык программирования С++ |
1996 |
Психология программирования |
1998 |
Основание и империя |
2000 |
Ожидаемый результат 2.1.6.b. |
b_name |
b_year |
Основание и империя |
2000 |
Психология программирования |
1998 |
Язык программирования С++ |
1996 |
Искусство программирования |
1993 |
Сказка о рыбаке и рыбке |
1990 |
Евгений Онегин |
1985 |
Курс теоретической физики |
1981 |
Решение 2.1.6.a{35}.
Для упорядочивания1 результатов выборки необходимо применить конструкцию ORDER BY (строка 4 каждого запроса), в которой мы указываем:
•поле, по которому производится сортировка (b_year)
•направление сортировки (ASC).
MySQL Решение 2.1.6.a
1SELECT `b_name`,
2`b_year`
3 |
|
FROM |
`books` |
|
|
|
|
4 |
|
ORDER |
BY `b_year` ASC |
MS SQL Решение 2.1.6.a
1SELECT [b_name],
2[b_year]
3 |
|
FROM |
[books] |
4 |
|
ORDER |
BY [b_year] ASC |
|
|
|
|
1 В повседневной жизни всё равно большинство людей использует тут термин «сортировка» вместо «упорядочивание», но это не совсем идентичные понятия. «Сортировка» больше относится к процессу изменения порядка, а «упорядочивание» к готовому результату.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 35/545
Пример 6: упорядочивание выборки
Oracle Решение 2.1.6.a
1SELECT "b_name",
2"b_year"
3 |
|
FROM |
"books" |
4 |
|
ORDER |
BY "b_year" ASC |
Решение 2.1.6.b{35}.
Здесь (в отличие от решения{35} задачи 2.1.6.a{35}) всего лишь необходимо поменять направление сортировки с «по возрастанию» (ASC) на «по убыванию»
(DESC).
MySQL Решение 2.1.6.b
1SELECT `b_name`,
2`b_year`
3 |
|
FROM |
`books` |
4 |
|
ORDER |
BY `b_year` DESC |
|
|
|
|
MS SQL Решение 2.1.6.b
1SELECT [b_name],
2[b_year]
3 |
|
FROM |
[books] |
4 |
|
ORDER |
BY [b_year] DESC |
Oracle Решение 2.1.6.b
1SELECT "b_name",
2"b_year"
3 |
|
FROM |
"books" |
4 |
|
ORDER |
BY "b_year" DESC |
Альтернативное решение можно получить добавлением знака «минус» перед именем поля, по которому сортировка реализована по возрастанию, т.е. ORDER
BY числовое_поле DESC эквивалентно ORDER BY -числовое_поле ASC.
MySQL Решение 2.1.6.b (альтернативный вариант)
1SELECT `b_name`,
2`b_year`
3 |
|
FROM |
`books` |
4 |
|
ORDER |
BY -`b_year` ASC |
|
|
|
|
MS SQL Решение 2.1.6.b (альтернативный вариант)
1SELECT [b_name],
2[b_year]
3 |
|
FROM |
[books] |
4 |
|
ORDER |
BY -[b_year] ASC |
Oracle Решение 2.1.6.b (альтернативный вариант)
1SELECT "b_name",
2"b_year"
3 |
|
FROM |
"books" |
4 |
|
ORDER |
BY -"b_year" ASC |
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 36/545
Пример 6: упорядочивание выборки
Исследование 2.1.6.EXP.A. Ещё одна неожиданная проблема с упорядочиванием связана с тем, где различные СУБД по умолчанию располагают NULL-значения — в начале выборки или в конце. Проверим.
Снова воспользуемся готовой таблицей table_with_nulls{26}. В ней попрежнему находятся следующие данные:
x
1
1
2
NULL
Выполним запросы 2.1.6.EXP.A:
MySQL |
Исследование 2.1.6.EXP.A |
||
1 |
SELECT |
`x` |
|
2 |
FROM |
`table_with_nulls` |
|
3 |
ORDER |
BY `x` DESC |
|
|
|
||
MS SQL |
Исследование 2.1.6.EXP.A |
||
1 |
SELECT |
[x] |
|
2 |
FROM |
[table_with_nulls] |
|
3 |
ORDER |
BY [x] DESC |
|
|
|
|
|
Oracle |
|
Исследование 2.1.6.EXP.A |
|
1 |
SELECT |
"x" |
|
2 |
FROM |
"table_with_nulls" |
|
3 |
ORDER |
BY "x" DESC |
Результаты будут следующими (обратите внимание на то, где расположено NULL-значение):
x |
|
x |
|
x |
2 |
|
2 |
|
NULL |
1 |
|
1 |
|
2 |
1 |
|
1 |
|
1 |
NULL |
|
NULL |
|
1 |
MySQL |
MS SQL Server |
Oracle |
Получить в MySQL и MS SQL Server поведение, аналогичное поведению Oracle (и наоборот), можно с использованием следующих запросов:
MySQL |
Исследование 2.1.6.EXP.A |
||
1 |
SELECT |
`x` |
|
2 |
FROM |
`table_with_nulls` |
|
3 |
ORDER |
BY `x` IS NULL DESC, |
|
4 |
|
|
`x` DESC |
|
|
||
MS SQL |
Исследование 2.1.6.EXP.A |
||
1 |
SELECT |
[x] |
|
2 |
FROM |
[table_with_nulls] |
|
3 |
ORDER |
BY ( CASE |
|
4 |
|
|
WHEN [x] IS NULL THEN 0 |
5 |
|
|
ELSE 1 |
6 |
|
|
END ) ASC, |
7 |
|
|
[x] DESC |
|
|
|
|
Oracle |
|
Исследование 2.1.6.EXP.A |
|
1 |
SELECT |
"x" |
|
2 |
FROM |
"table_with_nulls" |
|
3 |
ORDER |
BY "x" DESC NULLS LAST |
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 37/545
Пример 6: упорядочивание выборки
В случае с Oracle мы явно указываем, поместить ли NULL-значения в начало выборки (NULLS FIRST) или в конец выборки (NULLS LAST). Поскольку MySQL и MS SQL Server не поддерживают такой синтаксис, выборку приходится упорядочивать по двум уровням: первый уровень (строка 3 для MySQL, строки 3-6 для MS SQL Server) — по признаку «является ли значение поля NULL’ом», второй уровень
— по самому значению поля.
Задание 2.1.6.TSK.A: показать список авторов в обратном алфавитном порядке (т.е. «Я А».
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 38/545
Пример 7: использование составных условий
2.1.7. Пример 7: использование составных условий
Задача 2.1.7.a{39}: показать книги, изданные в период 1990-2000 годов, представленные в библиотеке в количестве трёх и более экземпляров.
Задача 2.1.7.b{40}: показать идентификаторы и даты выдачи книг за лето 2012-го года.
Ожидаемый результат 2.1.7.a.
|
b_name |
b_year |
b_quantity |
|
Сказка о рыбаке и рыбке |
1990 |
3 |
||
Основание и империя |
2000 |
5 |
||
Язык программирования С++ |
1996 |
3 |
||
Искусство программирования |
1993 |
7 |
||
|
Ожидаемый результат 2.1.7.b. |
|
||
|
|
|
|
|
sb_id |
sb_start |
|
|
|
42 |
2012-06-11 |
|
|
|
57 |
2012-06-11 |
|
|
|
Решение 2.1.7.a{39}.
Для каждой СУБД приведено два варианта запроса — с ключевым словом BETWEEN (часто используемого как раз для указания диапазона дат), и без него — в виде двойного неравенства (что выглядит более привычно для имеющих опыт программирования).
В случае использования BETWEEN, границы включаются в диапазон искомых значений.
В представленных ниже решениях отдельные условия осознанно не взяты в скобки. Синтаксически такой вариант верен и отлично работает, но он тем сложнее читается, чем больше составных частей входит в сложное условие. Потому всё же рекомендуется брать каждую отдельную часть в скобки.
MySQL Решение 2.1.7.a
1-- Вариант 1: использование BETWEEN
2SELECT `b_name`,
3`b_year`,
4`b_quantity`
5 |
|
FROM |
`books` |
|
6 |
|
WHERE |
`b_year` BETWEEN 1990 |
AND 2000 |
7 |
|
|
AND `b_quantity` >= 3 |
|
|
|
|
|
|
1-- Вариант 2: использование двойного неравенства
2SELECT `b_name`,
3`b_year`,
4`b_quantity`
5 |
|
FROM |
`books` |
6 |
|
WHERE |
`b_year` >= 1990 |
7AND `b_year` <= 2000
8AND `b_quantity` >= 3
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 39/545