Упражнение 25

Найдите производителей принтеров, которые производят ПК с наименьшим объемом RAM и с самым быстрым процессором среди всех ПК, имеющих наименьший объем RAM. Вывести: Maker

Ключевой здесь является фраза «имеющих наименьший объем RAM». Она не избыточна, как это может показаться на первый взгляд. Не достаточно найти все модели, имеющие максимальную скорость среди ПК с минимальной RAM.

Поясним сказанное демонстрацией неправильных решений. Для этой задачи их немало накопилось. Вот первый пример.

Решение 1.17.1

SELECT c.maker
FROM Product c,
     (SELECT b.model, MAX(b.speed) speed
      FROM PC b
      WHERE b.ram IN (SELECT MIN(a.ram)
                      FROM PC a
                      )
      GROUP BY b.model
      ) t
WHERE c.model = t.model
      AND EXISTS (SELECT d.model
              FROM Printer d, Product e
              WHERE d.model = e.model
                    AND e.maker = c.maker
              );
mssql
🚫
[[ error ]]
[[ column ]]
[[ value ]]
  1. Ошибка в подзапросе
(SELECT b.model, MAX(b.speed) speed
FROM PC b
WHERE b.ram IN (SELECT MIN(a.ram)
                FROM PC a
                )
GROUP BY b.model
) t

Здесь выбираются модели ПК с минимальной памятью, и для каждой такой модели определяется ПК с максимальной скоростью. Ошибка состоит в том, что максимальную скорость нужно определять по всем ПК с минимальной памятью, а не по каждой модели. Кроме того, если у производителя будет две модели с минимальной памятью, то он дважды попадет в результирующий набор, так как в запросе отсутствует устранение дубликатов (DISTINCT, например).

  1. Ошибка в определении производителей принтеров
AND EXISTS (SELECT d.model
            FROM Printer d, Product e
            WHERE d.model=e.model
                  AND e.maker = c.maker
            )

Мы уже обсуждали этот вопрос здесь.

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

Решение 1.17.2

SELECT DISTINCT maker
FROM Product
WHERE type = 'printer' AND
      maker IN(SELECT maker
               FROM Product
               WHERE model IN(SELECT model
                              FROM PC
                              WHERE speed = (SELECT MAX(speed)
                                             FROM (SELECT speed
                                                   FROM PC
                                                   WHERE ram=(SELECT MIN(ram)
                                                              FROM PC
                                                              )
                                                   ) AS z4
                                             )
                              )
               );
mssql
🚫
[[ error ]]
[[ column ]]
[[ value ]]

Вот как определяется здесь максимум по скорости среди моделей с минимальной памятью:

speed = (SELECT MAX(speed)
         FROM (SELECT speed
               FROM PC
               WHERE ram = (SELECT MIN(ram)
                            FROM PC
                            )
               ) AS z4
                    )

Что же осталось. Вернемся к формулировке, в которой требуются «ПК с наименьшим объемом RAM и с самым быстрым процессором среди всех ПК, имеющих наименьший объем RAM». Фактически, здесь содержится два условия:

ПК с наименьшим объемом RAM

и

ПК с самым быстрым процессором среди всех ПК, имеющих наименьший объем RAM

В рассматриваемом решении используется только второе из этих условий, а именно, определяются лишь модели, имеющие скорость, совпадающую с максимальной скоростью для моделей с минимальной памятью.

Поясним на примере. Пусть минимальная память для моделей ПК в БД — 64 Мбайт и имеются следующие модели:

Speedram
60064
600128
45064

Код, используемый для определения искомой скорости,

SELECT MAX(speed)
FROM (SELECT speed
      FROM PC
      WHERE ram = (SELECT MIN(ram)
                   FROM PC
                   )
      ) AS z4;
mssql
🚫
[[ error ]]
[[ column ]]
[[ value ]]
даст 600. Действительно, это максимальная скорость для моделей с минимальной (64) памятью. А далее мы отбираем модели с этой скоростью, куда попадает и модель {600, 128}, хотя она и не отвечает условиям задачи. Если производитель этой модели выпускает еще и принтеры (а он выпускает!), да к несчастью еще и не является производителем модели {600, 64}, то получаем «неверно» при проверке запроса.

Правильным выбором будет, естественно, лишь модель {600, 64}. Надеемся, что теперь решить эту задачу не составит труда.

Решить задачу на SQL-EX.RU