Database Programming & Design


HAVING без GROUP BY (I) - часть 2


Но формулировка, эквивалентная исходной и не включающая HAVING, все-таки существует. Она немного более хитрая:

SELECT DISTINCT ( SELECT SUM(SP.QTY) FROM SP) AS TQY FROM SP WHERE (SELECT MIN(SP.QTY) FROM SP) > 50 ;

При выполнении запроса в этой формулировке, если (внешние) разделы FROM и WHERE совместно производят пустую таблицу, то таким будет и результат всего запроса. Причина состоит в том, что единственный элемент, указанный в разделе SELECT является не ссылкой на агрегатную функцию SUM, а скалярным выражением, содержащим такую ссылку. Мощность окончательного результата (т.е. число строк в результирующей таблице) не зависит от вида этого скалярного выражения; можно было бы заменить (SELECT SUM ...) на SP.P#, на SP.QTY или даже на литерал. Более детально, происходит следующее:

  • Предположим, что условие раздела WHERE вычисляется в false для каждой строки SP.
  • Тогда разделы FROM и WHERE совместно производят пустую таблицу (без строк).
  • Подзапрос в разделе SELECT, конечно, возвращает значение 3100. (Более точно, он вырабатывает таблицу с одним столбцом и одной строкой, содержащей численное значение, но SQL извлекает это значение из таблицы. Здесь для нас это обстоятельство не слишком важно, но в SQL вообще оно вызывает проблемы.)
  • Итак, обсуждаемая формулировка запроса логически эквивалентна следующей:

    SELECT 3100 AS TQY FROM empty ;

    (empty именует пустую таблицу.) Очевидно, что результатом такого запроса является таблица с одним столбцом TQY и без строк.

Теперь мы можем сформулировать еще одно правило преобразования: Пусть имеется таблица R{A,B}, и agg1 и agg2 - агрегатные функции, применимые к R.A и R.B соответственно. Тогда выражение

SELECT agg1(R.A) AS C FROM R HAVING agg2(R.B) comp scalar ;

может быть логически преобразовано в эквивалентное выражение

SELECT DISTINCT ( SELECT agg1(R.A) FROM R ) AS C FROM R WHERE ( SELECT agg2(R.B) FROM R ) comp scalar ;

(Здесь comp - некоторый скалярный оператор сравнения, а scalar - некоторое скалярное выражение.)

Будем называть такие преобразования "преобразованиями Типа 3". Читателям рекомендуется самостоятельно разобрать случай, когда формулировка с HAVING включает раздел WHERE.




- Начало -  - Назад -  - Вперед -