ISNULL()
связан с SQL Server, поэтому этот вопрос, похоже, касается SQL Server.Как указано в комментариях, SQL Server запускает подзапрос дважды.
Кстати, это может быть детерминированным - и не только с подзапросами.Рассмотрим следующее выражение:
select coalesce(case when rand(checksum(newid())) < 0.5 then 'a' end, 'b')
Может возвращать значение NULL
- несмотря на COALESCE()
, поскольку первое выражение вычисляется дважды.Для интереса вы можете выполнить этот запрос:
select v.n, coalesce(case when rand(checksum(newid())) < 0.5 then 'a' end, 'b')
from (values (1), (2), (3), (4), (5), (6), (7), (8)) v(n);
Я могу предположить несколько причин, по которым SQL Server будет вести себя таким образом.
(1) Кто-то из Microsoft или Sybase (однаждывремя) на самом деле думал, что это правильный подход.
(2) Кто-то подумал: «У нас уже есть функция, которая делает это, поэтому COALESCE()
должно быть немного по-другому».Даже если из-за этой «маленькой разницы» это выглядит так, будто оно сломано.
(3) SQL Server не оптимизирует подзапросы, выполняя их только один раз (насколько я могу судить).Так что для подзапросов, в частности, идея могла бы звучать так: «мы исправим это на более позднем этапе оптимизации».
Это все домыслы (и, следовательно, мнение).Я хотел ответить, потому что это влияет не только на подзапросы.