Резюме
Там нет никакой логической причины , это не может быть сделано, но польза невелика , и есть некоторые подводные камни , которые могут быть не сразу.
Результаты исследований
Я провел небольшое исследование и нашел хорошую информацию. Ниже приводится прямая цитата из надежного первоисточника (который хочет остаться анонимным) в 2012-08-09 17:49 GMT:
Когда SQL был впервые изобретен, у него не было псевдонимов в предложении SELECT. Это был серьезный недостаток, который был исправлен, когда язык был стандартизирован ANSI примерно в 1986 году.
Язык был задуман как «непроцедурный» - другими словами, для описания данных, которые вы хотите, без указания того, как их найти. Итак, насколько я знаю, нет никаких причин, по которым реализация SQL не могла бы проанализировать весь запрос перед его обработкой и позволить определять псевдонимы где угодно и использовать везде. Например, я не вижу причин, по которым следующий запрос не должен быть действительным:
select name, salary + bonus as pay
from employee
where pay > 100000
Хотя я думаю, что это разумный запрос, некоторые системы на основе SQL могут вводить ограничения на использование псевдонимов по некоторым причинам, связанным с реализацией. Я не удивлен, узнав, что SQL Server делает это.
Я заинтересован в дальнейших исследованиях стандарта SQL-86 и в том, почему современные СУБД не поддерживают повторное использование псевдонимов, но у них еще не было времени продвинуться далеко вперед. Для начала, я не знаю, где взять документацию или как узнать, кто именно составлял комитет. Кто-нибудь может помочь? Я также хотел бы узнать больше об оригинальном продукте Sybase, из которого вышел SQL Server.
Из этого исследования и некоторых дальнейших размышлений я пришел к выводу, что использование псевдонимов в других разделах, хотя и вполне возможно, просто никогда не было таким высоким приоритетом для производителей СУБД по сравнению с другими языковыми функциями. Поскольку это не так уж и много препятствий, так как разработчик запросов легко его обходит, то прилагать усилия по сравнению с другими усовершенствованиями не оптимально. Кроме того, он будет проприетарным, поскольку он явно не является частью стандарта SQL (хотя я жду, чтобы узнать об этом наверняка), и, таким образом, будет незначительным улучшением, нарушающим совместимость SQL между СУБД. Для сравнения CROSS APPLY
(что на самом деле является не чем иным, как производной таблицей, допускающей внешние ссылки), это огромное изменение, которое в то время как проприетарная предлагает невероятную выразительную силу, которую нелегко выполнить другими способами.
Проблемы с использованием псевдонимов везде
Если вы разрешите помещать элементы SELECT в предложение WHERE, вы можете не только разбить сложность запроса (и, следовательно, сложность нахождения хорошего плана выполнения), но это может привести к совершенно нелогичным вещам. Пытаться:
SELECT X + 5 Y FROM MyTable WHERE Y = X
Что если MyTable уже имеет столбец Y, на который ссылается предложение WHERE? Решение состоит в том, чтобы использовать CTE или производную таблицу, которая в большинстве случаев не требует дополнительных затрат, но достигает того же конечного конечного результата. CTE и производные таблицы, по крайней мере, обеспечивают разрешение неоднозначности, позволяя использовать псевдоним только один раз.
Кроме того, исключительное использование псевдонимов в предложении FROM. Вы не можете сделать это:
SELECT
T3.ID + (SELECT Min(Interval) FROM Intervals WHERE IntName = 'T') CalcID
FROM
Table1 T
INNER JOIN Table2 T2
ON T2.ID = CalcID
INNER JOIN Table3 T3
ON T2.ID = T3.ID
Это циклическая ссылка (в том смысле, что T2 тайно ссылается на значение из T3, до того, как эта таблица была представлена в списке JOIN), и чертовски трудно увидеть. Как насчет этого:
INSERT dbo.FinalTransaction
SELECT
newid() FinalTransactionGUID,
'GUID is: ' + Convert(varchar(50), FinalTransactionGUID) TextGUID,
T.*
FROM
dbo.MyTable T
Сколько вы хотите поспорить, что функция newid () будет дважды включена в план выполнения, совершенно неожиданно заставив два столбца показывать разные значения? Как насчет того, когда вышеупомянутый запрос используется N уровней глубоко в CTE или производных таблицах. Я гарантирую, что проблема хуже, чем вы можете себе представить. Есть уже серьезные проблемы несогласованности о том, когда вещи оцениваются только один раз или в какой момент в плане запроса, и Microsoft заявила , что она не исправитнекоторые из них, потому что они правильно выражают алгебру запросов - если получаются неожиданные результаты, разбейте запрос на части. Разрешение цепных ссылок, обнаружение циклических ссылок через потенциально очень длинные такие цепочки - это довольно сложные проблемы. Внедрите параллелизм, и у вас будет кошмар в процессе становления.
Примечание. Использование псевдонима в WHERE или GROUP BY не изменит проблемы с такими функциями, как newid () или rand ().
SQL Server способ создания выражений многократного использования
CROSS APPLY / OUTER APPLY - это один из способов SQL Server для создания выражений, которые можно использовать в любом другом месте запроса (только не ранее в предложении FROM):
SELECT
X.CalcID
FROM
Table1 T
INNER JOIN Table3 T3
ON T.ID = T3.ID
CROSS APPLY (
SELECT
T3.ID + (SELECT Min(Interval) FROM Intervals WHERE IntName = 'T') CalcID
) X
INNER JOIN Table2 T2
ON T2.ID = X.CalcID
Это делает две вещи:
- Делает все выражения в CROSS APPLY получать «пространство имен» (псевдоним таблицы, здесь, X) и быть уникальным в этом пространстве имен.
- Повсюду становится очевидным не только то, что CalcID приходит из X, но также становится очевидным, почему вы не можете использовать что-либо из X при объединении таблиц T1 и T3, потому что X еще не был представлен.
Я на самом деле очень люблю CROSS APPLY. Он стал моим верным другом, и я использую его все время. Вам нужен частичный UNPIVOT (для которого потребуется PIVOT / UNPIVOT или UNPIVOT / PIVOT с использованием собственного синтаксиса)? Сделано с CROSS APPLY. Нужна расчетная величина, которая будет многократно использоваться? Выполнено. Нужно жестко навязать порядок выполнения вызовов через связанный сервер? Готово - с кричащим улучшением скорости. Нужно только один тип строки разделить на 2 строки или с дополнительными условиями? Выполнено.
Поэтому, по крайней мере, в СУБД SQL Server 2005 и более поздних версиях у вас больше нет причин для жалоб: CROSS APPLY - это то, как вы СУШИТЕ так, как вам хочется.
В Entity SQL вы МОЖЕТЕ использовать псевдонимы из выражений в других местах запроса в некоторых ситуациях:
Обратите внимание, что здесь вы ДОЛЖНЫ определить выражение в
GROUP BY
предложении, чтобы использовать его вSELECT
предложении.Это, очевидно , можно разрешить некоторые из такого рода псевдоним как-многоразовой-выражения в запросах SQL.
источник