Упражнение 7 (подсказки и решения)

Вот решение, которое использует соединение вместо объединения:

SELECT DISTINCT a.model,
    ISNULL(b.price, 0) + ISNULL(c.price, 0) + ISNULL(d.price, 0) price
FROM (((Product a 
        LEFT JOIN PC b ON a.model = b.model
            ) LEFT JOIN Laptop c ON a.model = c.model
                ) LEFT JOIN Printer d ON a.model = d.model
    )
WHERE a.maker = 'B';
🚫
[[ error ]]
[[ column ]]
NULL [[ value ]]

Здесь применяется три внешних (левых) соединения таблицы Product с каждой из продукционных таблиц.

Отсутствующие значения цены будут заполнены NULL-значениями. Например, для модели 1232 персонального компьютера цена блокнота и принтера будут NULL. Поэтому только один из трех ценовых столбцов может содержать значение для каждой строки результирующей выборки. Чтобы не определять, какой это столбец, в списке столбцов предложения SELECT используется конструкция

ISNULL(b.price, 0) + ISNULL(c.price, 0) + ISNULL(d.price, 0),

складывающая все три цены, заменяя предварительно NULL-значение нулем. Последнее необходимо, так как сложение с NULL-значением даст NULL. Использование в запросе нестандартной функции ISNULL(price, 0) не принципиально, так как не менее эффективно всю конструкцию можно заменить стандартным COALESCE, даже без суммирования:

COALESCE(b.price, c.price, d.price, 0)

И все же представленное решение имеет один недостаток. Представьте, что у производителя B есть модель, скажем 1133, которой нет в продукционной таблице. Тогда результатом выполнения запроса будет строка:

11330
с ценой $0. Такой результат дает неправильную информацию, так как продукции по такой цене нет. Чтобы согласовать данное решение с решением на основе объединения, которое не выводит строки с нулевой ценой, нужно добавить еще и условие отбора по цене. Сделайте это самостоятельно и
проверьте правильность своего решения.

Вернуться к обсуждению упражнения 7