Программирование >>  Преобразование значений null 

1 ... 203 204 205 [ 206 ] 207 208 209 ... 219


from student

s, take t

where s.sno =

t.sno

SNO SNAME

1 AARON

CS112

1 AARON

CS113

1 AARON

CS114

2 CHUCK

CS112

3 DOUG

CS112

3 DOUG

CS114

4 MAGGIE

CS112

4 MAGGIE

CS113

5 STEVE

CS113

6 JING

CS113

6 JING

CS114

Когда имеются наименования предметов и их количество, остается только выбрать строки, в которых значение CNT равно 1 и CNO равно CS112.

Оригинальное решение

Оригинальное решение использует подзапрос и двойное отрицание:

select s.* from student s, take t where s.sno = t.sno

and s.sno not in ( select sno from take

where cno != CS112 )

Это исключительно разумное решение: в запросе нет ни проверки количества изучаемых студентом предметов, ни фильтра, гарантирующего, что выбранные студенты действительно изучают CS112! Но тогда, как оно работает? Подзапрос возвращает всех студентов, изучающих не CS112. Результаты показаны ниже:

select sno from take where cno != CS112

В результате внешнего запроса выбираются студенты, которые изучают предмет (любой) и которых нет среди студентов, возвращенных



SNO SNAME

1 AARON

1 AARON

1 AARON

2 CHUCK

3 DOUG

3 DOUG

4 MAGGIE

4 MAGGIE

5 STEVE

6 JING

6 JING

Если сравним два результирующих множества, мы увидим, что введение NOT IN во внешний запрос эффективно обеспечивает вычитание из множества значений SNO, возвращаемых внешним запросом, множества значений SNO, возвращенных подзапросом, в результате чего будет возвращен студент, значение SNO которого равно 2. Итак, подзапрос находит всех студентов, изучающих не CS112. Внешний запрос возвращает студентов, которых нет среди изучающих не CS112 (здесь остаются студенты, которые изучают только CS112 или вообще не изучают ни одного предмета). В результате объединения таблиц STUDENT и TAKE студенты, не изучающие ни одного предмета, отсеиваются, и остаются только те, которые изучают CS112 и только этот предмет. Решение задачи на основе множеств в лучшем виде!

Запросы с условием не более

Вопросы с условием не более представляют другой тип задач, с которыми вы сталкиваетесь время от времени. Довольно просто найти строки, для которых условие выполняется. А если требуется ограничить количество таких строк? Этому посвящены следующие два запроса.

Запрос 4

Требуется найти студентов, изучающих не более двух предметов. Студенты, не изучающие ни одного предмета, не должны рассматриваться. Из всех студентов, изучающих какие-либо предметы, только AARON изучает их более двух и должен быть исключен из результирующего множества. В конечном счете, хотелось бы получить следующее результирующее множество:

подзапросом. Если на мгновение опустить часть NOT IN внешнего запроса, результаты будут следующими (выбираются все студенты, изучающие что-либо):

select s.* from student s, take t where s.sno = t.sno



SNO SNAME AGE

2 CHUCK 21

3 DOUG 20

4 MAGGIE 19

5 STEVE 22

6 JING 18

MySQL и PostgreSQL

Чтобы определить, кто из студентов изучает не более двух предметов, используйте агрегатную функцию COUNT:

1 select s.sno,s.sname,s.age

2 from student s, take t

3 where s.sno = t.sno

4 group by s.sno,s.sname,s.age

5 having count(*) <= 2

DB2, Oracle и SQL Server

Чтобы определить, кто из студентов изучает не более двух предметов, используйте оконную функцию COUNT OVER:

select

distinct sno,sname,age

from

select

s.sno,s.sname,s.age,

count(*) over (

partition by s.sno,s.sname,s.age

) as cnt

from

student s, take t

where

s.sno = t.sno

where

cnt <= 2

Обсуждение

В обоих решениях просто выполняется подсчет экземпляров значений SNO в таблице TAKE. Внутреннее объединение с таблицей TAKE гарантирует, что студенты, не изучающие ни одного предмета, будут исключены из окончательного результирующего множества.

Оригинальное решение

В своей книге Розенштейн использовал решение с агрегацией, показанное здесь для MySQL и PostgreSQL, а также предложил альтернативное решение с множеством рефлексивных объединений, которое можно увидеть ниже:

select distinct s.*

from student s, take t where s.sno = t.sno

and s.sno not in ( select t1.sno

from take t1, take t2, take t3



1 ... 203 204 205 [ 206 ] 207 208 209 ... 219

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика