Упражнение 8

Найдите производителя, продающего ПК, но не ноутбуки.

Начнем с ошибки новичка:

SELECT DISTINCT maker
FROM Product
WHERE type = 'PC' 
    AND NOT (type = 'Laptop');
mssql
🚫
[[ error ]]
[[ 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
                    );
mssql
🚫
[[ error ]]
[[ column ]]
[[ value ]]

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

ПиР

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