Почему COALESCE выполняет подзапрос дважды? - PullRequest
0 голосов
/ 24 февраля 2019

В настоящее время я узнаю о различиях между ISNULL и COALESCE, и я натолкнулся на утверждение, в котором говорится:

COALESCE((<subquery), 0)

переведено (согласно стандарту SQL):

CASE WHEN (<subquery>) IS NOT NULL THEN (<subquery>) ELSE 0 END

Мой вопрос: почему подзапрос выполняется дважды?Это кажется неэффективным.

1 Ответ

0 голосов
/ 24 февраля 2019

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 не оптимизирует подзапросы, выполняя их только один раз (насколько я могу судить).Так что для подзапросов, в частности, идея могла бы звучать так: «мы исправим это на более позднем этапе оптимизации».

Это все домыслы (и, следовательно, мнение).Я хотел ответить, потому что это влияет не только на подзапросы.

...