Упражнение 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';
[[ 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, которой нет в продукционной таблице. Тогда результатом выполнения запроса будет строка:
1133 | 0 |
с ценой $0. Такой результат дает неправильную информацию, так как продукции по такой цене нет. Чтобы согласовать данное решение с решением на основе объединения, которое не выводит строки с нулевой ценой, нужно добавить еще и условие отбора по цене. Сделайте это самостоятельно и | |
проверьте правильность своего решения. |