Почему я не могу использовать псевдоним для агрегата в условии наличия?
Мой код выглядит так:
select col1,count(col2) as col7
from --some join operation
group by col1
having col7 >= 3 -- replace col7 by count(col2) to make the code work
Мой код вызывает ошибку "Недопустимое имя столбца" col7 ". Почему это происходит? Кажется нелогичным, что SQL не позволяет мне использовать col7 в последней строке.
Я использую SQL Server express 2008
Ответы
Ответ 1
В MS SQL единственное место (я знаю), что вы можете ссылаться на псевдонимы, находится в предложении ORDER BY. Возможность ссылаться на псевдонимы в других частях запроса - это функция, которой обладают многие другие платформы db, и, честно говоря, она раздражает меня тем, что Microsoft не считает ее достаточно полезной функцией для ее добавления.
Ответ 2
Предложение HAVING
оценивается до SELECT
поэтому сервер еще не знает об этом псевдониме.
-
Сначала формируется произведение всех таблиц в предложении FROM
.
-
Затем выполняется предложение WHERE
чтобы исключить строки, которые не удовлетворяют условию search_condition.
-
Затем строки группируются с использованием столбцов в предложении GROUP BY
.
-
Затем группы, которые не удовлетворяют search_condition
в предложении HAVING
, удаляются.
-
Затем оцениваются выражения в целевом списке SELECT
.
-
Если ключевое слово DISTINCT
присутствует в предложении select, дублирующиеся строки теперь удаляются.
-
UNION
берется после каждого подвыбора.
-
Наконец, результирующие строки сортируются в соответствии со столбцами, указанными в предложении ORDER BY
.
-
Предложение TOP
выполнено.
Надеюсь, что это ответ на ваш вопрос. Также объясняется, почему псевдоним работает в предложении ORDER BY
.
Ответ 3
Попробуйте с этим, так как список выбора содержит одно и то же выражение, которое вы можете использовать и в условии:
SELECT COL1,COUNT(COL2) AS COL7
FROM --SOME JOIN OPERATION
GROUP BY COL1
HAVING COUNT(COL2) >= 3
Ответ 4
Вы должны выбрать дважды, чтобы использовать столбец count()
select * from (select col1,count(col2) as col7
from --some join operation
group by col1) as temp
where temp.col7 >= 3
Ответ 5
U может использовать этот код:
IF OBJECT_ID('tempdb..#temp') is not null DROP TABLE #temp
-- Create tempurary table
CREATE TABLE #temp (Id BIGINT IDENTITY(1,1), col1 BIGINT, countOfcol2 BIGIN)
--insert from the table 2 #temp
INSERT INTO #temp (col1,countOfcol2)
select col1,count(col2) as col7
from --some join operation
select col1,countOfcol2 from #temp
group by col1
having countOfcol2 >= 3 -- replace col7 by count(col2) to make the code work
Ответ 6
Вы можете решить это с помощью вложенного запроса.
Я также столкнулся с этой проблемой, когда я хочу улучшить производительность. Мне нужно было запустить count()
на основе определенных полей в пределах поля JSON в таблице, очевидно, что мы хотели бы проанализировать JSON только один раз, вместо того, чтобы включать отдельный счетчик в предложение where
или have
(особенно дорогой, такой как в моем случае).
Если col1
является уникальным идентификатором, самый эффективный в вычислительном отношении способ может заключаться во вложении счетчика в отдельный select
select col1, innerquery.col7
from whatevertable
inner join (select col1, count(col2) as col7
from whatevertable
group by col1) as innerquery
on innerquery.col1 = whatevertable.col1
where innerquery.col7 >= 3;
Таким образом, счетчик запускается только один раз, создавая временную таблицу поиска для справки по остальной части вашего запроса.
Опять же, это работает только в том случае, если col1
уникален для каждой записи, что обычно не слишком много, чтобы спросить, так как большинство таблиц имеют своего рода первичный ключ id.
Ответ 7
выберите col1, count (col2) как col7
от операции соединим
группа по col1
имея count (col2) >= 3;
Честно говоря, я удивлен, почему SQL Server не обрабатывает псевдоним столбца. Я использую это как обходной путь. Он по-прежнему печатает имя столбца в качестве псевдонима, но обрабатывает исходную функцию агрегата.