Главная страница
Навигация по странице:

  • Упражнение 13 Найдите среднюю скорость ПК, выпущенных производителем A Решение 1.10.1

  • DISTINCT

  • WHERE

  • лекция. Учебник по sql если вы хотите узнать, что такое sql этот сайт для вас


    Скачать 7.88 Mb.
    НазваниеУчебник по sql если вы хотите узнать, что такое sql этот сайт для вас
    Анкорлекция
    Дата21.12.2022
    Размер7.88 Mb.
    Формат файлаpdf
    Имя файлаMoiseenko_SQL.pdf
    ТипУчебник
    #857633
    страница3 из 47
    1   2   3   4   5   6   7   8   9   ...   47
    Упражнение 10
    Найдите модели принтеров, имеющих самую
    высокую цену. Вывести: model, price
    Задача обычно не вызывает затруднений, однако, иногда встречаются решения подобные следующему:
    1.
    SELECT
    model,
    MAX
    (
    DISTINCT
    price
    )
    2.
    FROM
    Printer
    3.
    GROUP
    BY
    model
    ;
    Понятно естественное желание решить задачу без подзапросов. Если бы требовалось вывести только максимальную цену, то тогда группировка была бы не нужна, так как максимум находился бы по всему набору принтеров:
    1.
    SELECT
    MAX
    (
    price
    )
    2.
    FROM
    Printer
    ;
    Однако в задаче требуется вывести еще и номер (номера) модели, имеющей максимальную цену.
    Поскольку мы не можем в предложении SELECT использовать агрегатные значения наряду с детализированными (если не использовать группировку по детализированным значениям), то в результате и получаем представленное выше неправильное решение с группировкой по модели. Это решение дает максимальную цену по каждой модели, нам же нужно получить модели, которые имеют абсолютную
    (по всему набору принтеров) максимальную цену.
    Итак, приходится использовать подзапрос, в котором вычисляется максимальная цена:

    1.
    SELECT
    model, price
    2.
    FROM
    Printer
    3.
    WHERE
    price =
    (
    SELECT
    MAX
    (
    price
    )
    4.
    FROM
    Printer
    5.
    )
    ;
    При этом подзапрос может вводиться не только с простым оператором сравнения («=»), но и с предложением IN или >= ALL.
    Подзапрос можно использовать и в предложении FROM:
    1.
    SELECT
    model, price
    2.
    FROM
    Printer pr,
    (
    SELECT
    MAX
    (
    price
    )
    AS
    maxprice
    3.
    FROM
    Printer
    4.
    )
    AS
    mp
    5.
    WHERE
    price = mp.maxprice;
    Однако это не дает выигрыша в производительности, так как в любом случае вычисление подзапроса выполняется один раз, а потом уже производится сравнение цен для каждой строки.
    И все же, можно ли решить задачу без подзапроса?
    Упражнение 13
    Найдите среднюю скорость ПК, выпущенных
    производителем A
    Решение 1.10.1. Характерная для начинающих ошибка, когда вновь изученные конструкции языка применяются к месту и ни к месту. Вот типичный пример:

    1.
    SELECT
    AVG
    (
    speed
    )
    AS
    avg_speed
    2.
    FROM
    PC
    3.
    WHERE
    speed
    IN
    (
    SELECT
    speed
    4.
    FROM
    PC, Product
    5.
    WHERE
    product.model = PC.model
    AND
    6. maker=
    'A'
    7.
    )
    ;
    Здесь в подзапросе предложения WHERE отбираются значения скорости процессора ПК, выпущенных производителем A. Далее вычисляется средняя скорость по всем тем ПК, скорость процессора у которых совпадает с одним из значений в списке, полученным из подзапроса. В результате будет учтена и скорость ПК, скажем, производителя B, если она совпадает со скоростью одного из ПК, выпущенного производителем A. Правильный результат будет получен только в том случае, если производители ПК обладают моделями с уникальными наборами скоростей процессора.
    Упражнение 15
    Найдите размеры жестких дисков,
    совпадающих у двух и более PC. Вывести: HD
    Неверное решение связано с поверхностным знакомством со схемой данных:
    Решение 1.11.1
    1.
    SELECT
    DISTINCT
    t.hd
    2.
    FROM
    PC t
    3.
    WHERE
    EXISTS
    (
    SELECT
    *
    4.
    FROM
    PC
    5.
    WHERE
    pc.hd = t.hd
    AND

    6. pc.model <> t.model
    7.
    )
    ;
    В запросе находятся такие ПК, для которых существует другая модель с таким же размером жесткого диска. Ошибка заключается в интуитивном представлении об уникальности модели в таблице PC. Однако, как мы уже говорили, номера моделей уникальны лишь в таблице Product, а здесь они могут повторяться, что и делает данный запрос неверным, так как исключает из рассмотрения одинаковые модели с одинаковыми размерами жестких дисков.
    Упражнение 16
    Найдите пары моделей PC, имеющих
    одинаковые скорость и RAM. В результате
    каждая пара указывается только один раз,
    то есть (i,j), но не (j,i), Порядок вывода:
    модель с большим номером, модель с
    меньшим номером, скорость и RAM
    Вот решение, которое довольно часто встречается у посетителей сайта:
    1.
    SELECT
    MAX
    (
    model
    )
    AS
    'model'
    ,
    MIN
    (
    model
    )
    AS
    'model'
    , speed, ram
    2.
    FROM
    PC
    3.
    GROUP
    BY
    speed, ram
    4.
    HAVING
    MAX
    (
    model
    )
    >
    MIN
    (
    model
    )
    ;
    Не известно, по какой причине выводят только максимальную и минимальную модель для каждой совпадающей пары значений speed, ram.
    Возможно, в заблуждение вводит результат «правильного» запроса на основной базе.

    В этой задаче требуется упорядочить все модели, а не только максимальную и минимальную.
    Экстремальные характеристики упомянуты для однозначности, то есть, чтобы выводить пару моделей один раз, например:
    11221121 но не
    11211122
    То есть если, скажем, три модели — 1122, 1121, 1135 — имеют одинаковые характеристики, то вывод должен быть таким:
    1135 1122 1135 1121 1122 1121
    Ниже представлено почти правильное, хотя и громоздкое решение.
    Решение 1.12.2
    1.
    SELECT
    P.model, L.model, P.speed, P.ram
    2.
    FROM
    PC P
    JOIN
    3.
    (
    SELECT
    speed, ram
    4.
    FROM
    PC
    5.
    GROUP
    BY
    speed, ram
    6.
    HAVING
    SUM
    (
    speed
    )
    /speed =
    2
    AND
    7.
    SUM
    (
    ram
    )
    /ram =
    2 8.
    )
    S
    ON
    P.speed = S.speed
    AND
    9. P.ram = S.ram
    JOIN
    10.
    PC L
    ON
    L.speed = S.speed
    AND
    11.
    L.ram = S.ram
    AND
    12.
    L.model < P.model;
    Здесь в подзапросе S отбираются уникальные пары характеристик (скорость, память), совпадающие у двух ПК (SUM(speed)/speed = 2) — сумма
    одинаковых значений, деленная на это значение, дает количество ПК. Хотя с тем же успехом можно было написать такое предложение HAVING:
    1.
    HAVING
    COUNT
    (
    *
    )
    =
    2
    Подзапрос дважды соединяется с таблицей PC по этой паре характеристик.
    При этом второе соединение выполняется лишь для того, чтобы упорядочить модели (L.model < P.model).
    Ошибка данного решения состоит в том, что число ПК с одинаковыми характеристиками может быть больше двух. В этой ситуации ни одна из таких моделей не попадет в результирующий набор представленного решения.
    Несмотря на то, что решение легко исправить, лучше написать его не в такой избыточной форме.
    Еще одна типичная ошибка при решении данного упражнения вызвана возможным наличием в таблице PC компьютеров одинаковых моделей. В связи с этим при выводе пар ПК необходимо исключать дубликаты.
    Упражнение 17
    Найдите портативные компьютеры,
    скорость которых меньше скорости любого
    ПК. Вывести: type, model, speed
    Ошибки, которые здесь допускаются, связаны с излишним использованием операций соединения.
    Самым вопиющим примером, по мнению автора, является следующий:
    1.
    SELECT
    DISTINCT
    p.type, l.model, l.speed
    2.
    FROM
    Product p, Laptop l, PC c
    3.
    WHERE
    l.speed <
    (
    SELECT
    MIN
    (
    speed
    )
    4.
    FROM
    PC
    5.
    )
    AND

    6. p.type =
    'laptop'
    ;
    В предложении FROM используется декартово произведение трех таблиц!
    Если присутствие таблицы Product еще можно как-то оправдать — ведь в задаче требуется указать еще и тип продукции, то таблицу PC можно смело исключить — это не повлияет на результат. Естественно, решение не будет оптимальным по скорости выполнения. Кроме того, могут возникнуть проблемы с памятью, так как мощность промежуточного результата может стать огромной даже для относительно небольших таблиц. Напомним, что мощность декартового произведения равна произведению мощностей операндов. Например, для таблиц с количеством строк 100, 500 и 1000 их декартово произведение будет содержать 50000000 строк!
    И, тем не менее, решение является правильным, так как предложение
    DISTINCT исключает все дубликаты, появившиеся в результате декартового произведения.
    Упражнение 18
    Найдите производителей самых дешевых
    цветных принтеров. Вывести: maker, price
    Найдите две ошибки в следующем решении:
    1.
    SELECT
    c.maker, a.priceA price
    2.
    FROM
    (
    SELECT
    MIN
    (
    price
    )
    priceA
    3.
    FROM
    Printer
    4.
    WHERE
    color =
    'y'
    5.
    )
    a
    INNER
    JOIN
    6. Printer b
    ON
    a.priceA = b.price
    INNER
    JOIN
    7. Product c
    ON
    b.model = c.model;
    Упражнение 20

    Найдите производителей, выпускающих по
    меньшей мере три различных модели ПК.
    Вывести: Maker, число моделей
    Новички часто задают вопрос:
    "Почему правильным решением считается производитель Е с тремя моделями, хотя запрос
    1.
    SELECT
    Product.maker, PC.model
    2.
    FROM
    PC, Product
    3.
    WHERE
    Product
    .model = PC.model; показывает, что у этого производителя имеется всего одна модель?"
    Модели, которые в принципе выпускаются тем или иным производителем, содержатся в таблице Product. О таблице PC можно сказать, что это информация о компьютерах имеющихся в наличии. Соединение таблиц ограничивает выборку только моделями (вернее, конкретными ПК), имеющимися в наличии.
    Поскольку в задании говорится о моделях производителей, а не о имеющихся
    ПК, то нужно анализировать только таблицу Product. В результате обнаружатся недостающие модели.
    Упражнение 23
    Найдите производителей, которые
    производили бы как ПК со скоростью не
    менее 750 МГц, так и портативные
    компьютеры со скоростью не менее 750 МГц.
    Вывести: Maker
    Нижеприведенный запрос содержит характерную ошибку, допускаемую при решении этого упражнения.
    Решение 1.15.1

    1.
    SELECT
    DISTINCT
    maker
    2.
    FROM
    product
    3.
    WHERE
    model
    IN
    (
    SELECT
    model
    4.
    FROM
    PC
    5.
    WHERE
    speed >=
    750 6.
    )
    OR
    7. model
    IN
    (
    SELECT
    model
    8.
    FROM
    Laptop
    9.
    WHERE
    speed >=
    750 10.
    )
    ;
    Ошибка состоит в том, что в результирующий набор попадет также и производитель, выпускающий что-нибудь одно: либо ПК, либо портативные компьютеры, так как предикат в предложении WHERE будет истинен при выполнении хотя бы одного из условий, соединяемых оператором OR. Такой подход не удовлетворяет условиям задачи и совершенно справедливо отвергается системой.
    Вот попытка «изменить» ситуацию в лучшую сторону:
    Решение 1.15.2
    1.
    SELECT
    DISTINCT
    maker
    2.
    FROM
    Product a, PC b, Laptop c
    3.
    WHERE
    b.speed >=
    750
    AND
    4. c.speed >=
    750
    AND
    5.
    (
    a.model = b.model
    OR
    6. a.model = c.model
    7.
    )
    ;
    Используя равенство предикатов
    1. x
    AND
    (
    y
    OR
    z
    )
    =
    (
    x
    AND
    y
    )
    OR
    (
    x
    AND
    z
    )
    , выполним синтаксические преобразования рассматриваемого запроса:

    1.
    SELECT
    DISTINCT
    maker
    2.
    FROM
    Product a, PC b, Laptop c
    3.
    WHERE
    ((
    b.speed >=
    750
    AND
    4. c.speed >=
    750 5.
    )
    AND
    6. a.model = b.model
    7.
    )
    OR
    8.
    ((
    b.speed >=
    750
    AND
    9. c.speed >=
    750 10.
    )
    AND
    11. a.model = c.model
    12.
    )
    ;
    В результирующий набор попадут строки, удовлетворяющие хотя бы одному из предикатов, соединяемых оператором OR. Рассмотрим, например, запрос с первым предикатом:
    1.
    SELECT
    DISTINCT
    maker
    2.
    FROM
    Product a, PC b, Laptop c
    3.
    WHERE
    ((
    b.speed >=
    750
    AND
    4. c.speed >=
    750 5.
    )
    AND
    6. a.model = b.model
    7.
    )
    ;
    Перепишем его в синтаксически более удобной форме:
    1.
    SELECT
    DISTINCT
    maker
    2.
    FROM
    Product a
    JOIN
    3. PC b
    ON
    a.model = b.model,
    4. Laptop c
    5.
    WHERE
    (
    b.speed >=
    750
    AND
    6. c.speed >=
    750 7.
    )
    ;
    и далее
    1.
    SELECT
    DISTINCT
    maker
    2.
    FROM
    (
    SELECT
    maker
    3.
    FROM
    Product a
    JOIN
    4. PC b
    ON
    a.model = b.model
    5.
    WHERE
    b.speed >=
    750 6.
    )
    x,
    7.
    (
    SELECT
    *
    8.
    FROM
    Laptop c
    9.
    WHERE
    c.speed >=
    750 10.
    )
    y;
    Теперь, пожалуй, уже можно проанализировать. Первый подзапрос, который мы обозначили х соединяет по внешнему ключу таблицу PC с таблицей
    Product, отбирая производителей ПК со скоростью больше или равной 750.
    Второй подзапрос (y) фильтрует модели портативных компьютеров со скоростью больше или равной 750.
    То, как соединяются x и y, называется декартовым произведением. То есть производитель требуемых ПК будет в результирующем наборе сочетаться с каждой моделью ПК-блокнота, даже если она произведена другим производителем.
    В результате мы опять получим производителей, которые могут производить только что-то одно. Некоторая разница по сравнению с первым решением заключается в том, что если ни один производитель не выпускает портативные компьютеры с требуемой скоростью, то мы получим пустой набор записей.
    Этот частично правильный результат не дает первый пример 1.15.1
    Совпадение результатов на основной базе является совершенно случайным.
    Так уж оказалось, что те производители, которые выпускают требуемые по условию задачи ПК, выпускаю также и нужные портативные компьютеры.
    Таким образом, несмотря на совпадение результатов на «видимой» базе, запрос не является правильным при любом совместимом со схемой состоянием базы данных.
    Чтобы не быть голословным, покажем результаты оригинального запроса
    1.15.2
    с расширением списка выводимых столбцов:

    1.
    SELECT
    maker, a.model a_m, b.model b_m, c.model c_m
    2.
    FROM
    Product a, PC b, Laptop c
    3.
    WHERE
    ((
    b.speed >=
    750
    AND
    4. c.speed >=
    750 5.
    )
    AND
    6. a.model = b.model
    7.
    )
    OR
    8.
    ((
    b.speed >=
    750
    AND
    9. c.speed >=
    750 10.
    )
    AND
    11. a.model = c.model
    12.
    )
    ;
    Рассмотрим пару строк из результирующего набора:
    maker
    a_m
    b_m
    c_m
    B
    1121 1121 1752
    A
    1752 1121 1752
    Как видно, модель 1121 (ПК) принадлежит производителю В, а модель 1752
    (портативный компьютер) — производителю А. Так что у нас нет никаких оснований считать, что оба эти производителя удовлетворяют условиям задачи.
    Объединение требуемых моделей ПК и портативных компьютеров в один набор дает лишь иллюзию, что мы получаем и то, и другое:
    Решение 1.15.3
    1.
    SELECT
    maker
    2.
    FROM
    (
    SELECT
    maker
    3.
    FROM
    Product
    INNER
    JOIN
    4. PC
    ON
    Product.model = PC.model
    5.
    WHERE
    type=
    'PC'
    AND
    6. speed >=
    750 7.
    UNION
    ALL

    8.
    SELECT
    maker
    9.
    FROM
    Product
    INNER
    JOIN
    10.
    Laptop
    ON
    Product.model = Laptop.model
    11.
    WHERE
    type=
    'laptop'
    AND
    12. speed >=
    750 13.
    )
    S
    14.
    GROUP
    BY
    maker;
    В результате будет получен список производителей, для которых имеется хотя бы одна строка в наборе из предложения FROM. Ниже более короткий вариант той же ошибки.
    Решение 1.15.4
    1.
    SELECT
    maker
    2.
    FROM
    Product
    3.
    WHERE
    model
    IN
    (
    SELECT
    model
    4.
    FROM
    PC
    5.
    WHERE
    speed >=
    750 6.
    UNION
    ALL
    7.
    SELECT
    model
    8.
    FROM
    Laptop
    9.
    WHERE
    speed >=
    750 10.
    )
    11.
    GROUP
    BY
    maker;
    Следующее решение использует соединение.
    Решение 1.15.5
    1.
    SELECT
    maker
    2.
    FROM
    Product
    INNER
    JOIN
    3. PC
    ON
    Product.model = PC.model
    INNER
    JOIN
    4. Laptop
    ON
    Laptop.model = Product.model
    5.
    WHERE
    PC.speed >=
    750
    AND
    6. Laptop.speed >=
    750 7.
    GROUP
    BY
    maker;

    Идея состоит в следующем: получить в результирующей таблице столбец с именем производителя, столбец со скоростью ПК этого производителя, а также столбец со скоростью портативного компьютера того же производителя.
    Поэтому, если задать нужные ограничения на скорости, то строки, удовлетворяющие этим ограничениям, должны дать то, что нужно
    (группировка по производителю устраняет дубликаты). Идея правильная, однако, соединяется не то и не по тем предикатам.
    Действительно, первое внутреннее соединение даст нам список производителей и номера моделей ПК. Только ПК, так как model — первичный ключ в таблице Product. Поэтому второе внутреннее соединение с таблицей Laptop (по столбцу model!) даст нам пустой результирующий набор, так как в таблице Laptop нет (и не может быть!) моделей ПК.
    Чтобы реализовать эту идею, нужно соединять производителей нужных ПК с аналогичными производителями портативных компьютеров, но не по номеру модели, а по имени производителя, или же использовать внешние соединения, а не внутренние.
    Упражнение 24
    Найдите номер модели продукта (ПК, ПК-
    блокнота или принтера), имеющего самую
    высокую цену. Вывести: model
    Вот ошибочное решение, которое какое-то время назад принималось проверочной системой сайта:
    Решение 1.16.1
    1.
    SELECT
    model
    2.
    FROM
    (
    SELECT
    model, price
    3.
    FROM
    PC
    4.
    WHERE
    price =
    (
    SELECT
    MAX
    (
    price
    )
    5.
    FROM
    PC
    6.
    )
    7.
    UNION
    8.
    SELECT
    model, price

    9.
    FROM
    Laptop
    10.
    WHERE
    price =
    (
    SELECT
    MAX
    (
    price
    )
    11.
    FROM
    Laptop
    12.
    )
    13.
    UNION
    14.
    SELECT
    model, price
    15.
    FROM
    Printer
    16.
    WHERE
    price =
    (
    SELECT
    MAX
    (
    price
    )
    17.
    FROM
    Printer
    18.
    )
    19.
    )
    T
    20.
    WHERE
    price =
    (
    SELECT
    MAX
    (
    price
    )
    21.
    FROM
    Laptop
    22.
    )
    ;
    Давайте разберемся, какие данные должны быть в проверочной базе, чтобы блокировались такие решения.
    Но сначала посмотрим, что же делает этот запрос. В каждом из трех аналогичных подзапросов разыскиваются максимальные по цене модели по каждому из трех видов продукции — ПК, портативным компьютерам и принтерам. Далее используется оператор UNION для объединения найденных моделей, что, помимо этого, устраняет дубликаты строк модель, цена.
    Наконец, отбираются только те модели, цена которых совпадает с максимальной ценой на портативные компьютеры.
    Поэтому, если максимальной окажется цена на принтеры, то данное решение не будет приниматься системой. Но тогда будет приниматься решение, в котором условие отбора будет следующим:
    1.
    WHERE
    price =
    (
    SELECT
    MAX
    (
    price
    )
    2.
    FROM
    Printer
    3.
    )
    Более того, если максимальная цена будет у моделей только одного типа продукции (скажем, принтеров), то будет приниматься еще более неправильно решение:
    1   2   3   4   5   6   7   8   9   ...   47


    написать администратору сайта