Материал: Using_MySql,_MS_SQL_Server_and_Oracle

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

Пример 14: нетривиальные случаи использования условия IN и запросов на объединение

Oracle

Решение 2.2.4.a

1

SELECT

 

2

 

" s_id" , "s name"

3

FROM

"subscribers"

4

 

LEFT OUTER JOIN "subscriptions"

5

 

ON "s id" = "sb subscriber"

6

GROUP

BY "s id",

7

 

"s name"

8

HAVING COUNT(CASE

9

 

WHEN "sb_is_active" = 'Y' THEN "sb_is_active"

10

 

ELSE NULL

11

 

END) = 0

 

 

 

Почему получается такое нетривиальное решение? Строки 1-5 запросов 2.2.4. a возвращают следующие данные (добавим поле sb_is_active для наглядности):

s id

s name

sb is active

1

Иванов И.И.

N

1

Иванов И.И.

N

1

Иванов И.И.

N

1

Иванов И.И.

N

1

Иванов И.И.

N

2

Петров П.П.

NULL

3

Сидоров С.С.

Y

3

Сидоров С.С.

Y

3

Сидоров С.С.

Y

4

Сидоров С.С.

N

4

Сидоров С.С.

Y

4

Сидоров С.С.

Y

Признаком того, что читатель вернул все книги, является отсутствие (COUNT (...) = 0) у него записей со значением sb_is_active = 'Y'. Проблема в том, что мы не можем «заставить» COUNT считать только значения Y — он будет учитывать любые значения, не равные NULL. Отсюда легко следует вывод, что нам осталось превратить в NULL любые значения поля sb_is_active, не равные Y, т.е. получить такой результат:

s id

s name

sb is active

1

Иванов И.И.

NULL

1

Иванов И.И.

NULL

1

Иванов И.И.

NULL

1

Иванов И.И.

NULL

1

Иванов И.И.

NULL

2

Петров П.П.

NULL

3

Сидоров С.С.

Y

3

Сидоров С.С.

Y

3

Сидоров С.С.

Y

4

Сидоров С.С.

NULL

4

Сидоров С.С.

Y

4

Сидоров С.С.

Y

Именно за это действие отвечают выражения IF в строке 7 запроса для

Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 100/545

Пример 14: нетривиальные случаи использования условия IN и запросов на объединение

MySQL и CASE в строках 8-11 запросов для MS SQL Server и Oracle — любое значение поля sb_is_active, отличное от Y, они превращают в NULL.

Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 101/545

Пример 14: нетривиальные случаи использования условия IN и запросов на объединение

Теперь остаётся проверить результат работы COUNT: если он равен нулю, у читателя на руках нет книг.

Типичной ошибкой при решении задачи 2.2.4.а является попытка полу- XLV чить нужный результат следующим запросом:

 

Здесь получается такой неверный набор данных:

 

 

 

s_id

s_name

 

2

Петров П.П.

 

Это решение учитывает никогда не бравших книги читателей (sb_is_active IS NULL), а также тех, у кого есть на руках хотя бы одна книга (sb_is_active = 'Y'), но те, кто вернул все книги, под это условие не подходят:

s_id

s_name

sb_is_active

 

1

Иванов И.И.

N

 

1

Иванов И.И.

N

Эти записи не удовлетворяют

1

Иванов И.И.

N

условию WHERE и будут

1

Иванов И.И.

N

пропущены.

1

Иванов И.И.

N

 

2

Петров П.П.

NULL

 

3

Сидоров С.С.

Y

 

3

Сидоров С.С.

Y

 

3

Сидоров С.С.

Y

 

4

Сидоров С.С.

N

 

4

Сидоров С.С.

Y

 

4

Сидоров С.С.

Y

 

Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 102/545

Пример 14: нетривиальные случаи использования условия IN и запросов на объединение

Таким образом, Иванов И.И. оказывается пропущенным. Поэтому нужно использовать решение, представленное в начале рассмотрения задачи 2.2.4. а (т.е. решение с преобразованием значения поля sb_is_active).

'Vf Решение 2.2.4.b{92}.

Типичной ошибкой при решении задачи 2.2.4. b является попытка получить нужный результат следующим запросом:

 

MySQL

 

Решение 2.2.4.b (ошибочный запрос)

 

 

1

 

SELECT

 

's id',

 

 

 

2

 

 

 

 

's name'

 

 

 

 

 

 

 

 

 

 

3

 

FROM

 

 

'subscribers'

 

 

 

4

 

WHERE

 

's id' IN (SELECT

DISTINCT 'sb subscriber'

 

5

 

 

 

 

 

FROM

'subscriptions'

 

6

 

 

 

 

 

WHERE

'sb is active' = 'N')

 

MS SQL I

Решение 2.2.4.b (ошибочный запрос)

|

 

1

 

SELECT

 

[s id],

 

 

 

2

 

 

 

 

[s name]

 

 

 

 

 

 

 

 

 

 

3

 

FROM

 

 

[subscribers]

 

 

 

4

 

WHERE

 

[s id] IN (SELECT

DISTINCT [sb subscriber]

 

5

 

 

 

 

 

FROM

[ subscriptions]

 

6

 

 

 

 

 

WHERE

[sb is active] = 'N')

 

Oracle

 

Решение 2.2.4.b (ошибочный запрос)

 

 

1

 

SELECT

"s id",

 

 

 

2

 

 

 

"s name"

 

 

 

3

 

FROM

 

"subscribers"

 

 

 

4

 

WHERE

"s id" IN (SELECT

DISTINCT "sb subscriber"

 

5

 

 

 

 

 

FROM

"subscriptions"

 

6

 

 

 

 

 

WHERE

"sb is active" = 'N')

 

 

 

Получается такой набор данных:

 

 

 

 

 

 

 

 

 

 

s_id

s_name

 

 

 

1

 

Иванов И.И.

 

 

 

4

 

Сидоров С.С.

 

 

 

Но это — решение задачи «показать читателей, которые хотя бы раз вернули

Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 103/545

Пример 14: нетривиальные случаи использования условия IN и запросов на объединение

книгу». Данная проблема (характерная для многих подобных ситуаций) лежит не столько в области правильности составления запросов, сколько в области понимания смысла (семантики) модели базы данных.

Если по некоторому факту выдачи книги отмечено, что она возвращена (в поле sb_is_active стоит значение N), это совершенно не означает, что рядом нет другого факта выдачи тому же читателю книги, которую он ещё не вернул. Рассмотрим это на примере читателя с идентификатором 4 («Сидоров С.С.»):

sb_id

sb_subscriber

sb_book

sb_start

sb_finish

sb_is_active

57......

4

5

2012-06-1Ї

N

2012-08-11 -

 

91-"

4

1

2015-10-07

-2015-03-07 -

Y

4

 

2015-10-08

2025-11-08

Y

99 .......

4

 

Он вернул одну книгу, и потому подзапрос вернёт его идентификатор, но ещё две книги он не вернул, и потому по условию исходной задачи он не должен оказаться в списке.

Также очевидно, что читатели, никогда не бравшие книг, не попадут в список людей, у которых на руках нет книг (идентификаторы таких читателей вообще ни разу не встречаются в таблице subscriptions).

Задание 2.2.4.TSK.A: показать список книг, ни один экземпляр которых сейчас не находится на руках у читателей.

Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 104/545

Источник: https://studfile.net/preview/16420333/