Упражнение 8
Начнем с ошибки новичка:
SELECT DISTINCT maker
FROM Product
WHERE type = 'PC'
AND NOT (type = 'Laptop');
[[ column ]] |
---|
[[ value ]] |
Предикат в предложении WHERE проверяется для каждой строки, формируемой предложением FROM, то есть в нашем случае для каждой строки из таблицы Product. Каждая строка представляет собой некоторую модель, которая может быть чем-то одним, либо ПК, либо ноутбуком, либо принтером. Поэтому, если выполнен первый предикат (type = ‘PC’), то автоматически будет выполнен и второй — NOT (type = ‘Laptop’). Другими словами, второй предикат здесь излишен. Нам же нужно убедиться в том, что если есть строка с типом PC, то нет другой строки с типом Laptop для того же поставщика.
Второе решение, верное по логике, опирается на неверную трактовку предметной области, которую мы уже обсуждали:
SELECT DISTINCT p.maker
FROM Product p
INNER JOIN PC ON p.model = PC.model
WHERE p.maker NOT IN (SELECT ip.maker
FROM Laptop il
INNER JOIN Product ip ON il.model = ip.model
);
[[ column ]] |
---|
[[ value ]] |
Здесь проверяется наличие модели ПК в таблице PC и отсутствие модели ноутбуков для одного и того же поставщика. Ошибка заключается в том, что мы можем получить как лишних поставщиков (если в текущем состоянии базы данных в таблице Laptop отсутствуют модели некоего производителя ПК, хотя они и есть в Product), так и недосчитаться нужных (если в текущем состоянии базы данных в таблице PC нет ни одной модели некоторого поставщика, не производящего ноутбуки).