SQL Server AS с псевдонимом столбца в инструкции WHERE
Я хочу выполнить запрос, в котором я переименовываю один из столбцов, используя оператор "AS", и повторно использую это имя псевдонимого столбца в инструкции "WHERE". Ниже приведен пример:
SELECT lat AS latitude
FROM poi_table
WHERE latitude < 500
Проблема здесь в том, что SQL Server не нравится этот запрос из-за предложения WHERE и имени оператора AS, на которое ссылаются в предложении WHERE. Может ли кто-нибудь объяснить, почему это происходит, и что я могу сделать, чтобы исправить мою ситуацию?
Предположим, что у меня должна быть формула, которую я использовал в SELECT-части запроса, как мне это решить?
SELECT *,
( 6371*1000 * acos( cos( radians(42.3936868308) ) * cos( radians( lat ) ) * cos( radians( lon ) - radians(-72.5277256966) ) + sin( radians(42.3936868308) ) * sin( radians( lat ) ) ) )
AS distance
FROM poi_table
WHERE distance < 500;
Ответы
Ответ 1
SQL обычно не позволяет ссылаться на псевдонимы столбцов в предложениях WHERE, GROUP BY или HAVING. MySQL поддерживает ссылки на псевдонимы столбцов в GROUP BY и HAVING, но я подчеркиваю, что это вызовет проблемы при переносе таких запросов в другие базы данных.
В случае сомнений используйте фактическое имя столбца:
SELECT t.lat AS latitude
FROM poi_table t
WHERE t.lat < 500
Я добавил псевдоним таблицы, чтобы упростить просмотр фактического столбца с псевдонимом.
Update
Вычисленный столбец, подобный тому, который вы видите здесь:
SELECT *,
( 6371*1000 * acos( cos( radians(42.3936868308) ) * cos( radians( lat ) ) * cos( radians( lon ) - radians(-72.5277256966) ) + sin( radians(42.3936868308) ) * sin( radians( lat ) ) ) ) AS distance
FROM poi_table
WHERE distance < 500;
... не изменяет, что вы не можете ссылаться на псевдоним столбца в предложении WHERE. Чтобы этот запрос работал, вам нужно будет использовать:
SELECT *,
( 6371*1000 * acos( cos( radians(42.3936868308) ) * cos( radians( lat ) ) * cos( radians( lon ) - radians(-72.5277256966) ) + sin( radians(42.3936868308) ) * sin( radians( lat ) ) ) ) AS distance
FROM poi_table
WHERE ( 6371*1000 * acos( cos( radians(42.3936868308) ) * cos( radians( lat ) ) * cos( radians( lon ) - radians(-72.5277256966) ) + sin( radians(42.3936868308) ) * sin( radians( lat ) ) ) ) < 500;
Помните, что использование функции в столбце (IE: RADIANS(lat)
) сделает индекс бесполезным, если он существует в столбце.
Ответ 2
SQL Server настроен на применение фильтров до того, как он применит псевдонимы (поскольку это обычно приводит к более быстрым результатам).
Вы можете сделать вложенный оператор select. Пример:
SELECT Latitude FROM
(
SELECT Lat AS Latitude FROM poi_table
) A
WHERE Latitude < 500
Я понимаю, что это может быть не то, что вы ищете, потому что это делает ваши запросы более многословными.
Более сжатым подходом было бы сделать представление, которое обертывает вашу базовую таблицу:
CREATE VIEW vPoi_Table AS
SELECT Lat AS Latitude FROM poi_table
Тогда вы могли бы сказать:
SELECT Latitude FROM vPoi_Table WHERE Latitude < 500
Ответ 3
Я не уверен, почему вы не можете использовать "lat", но если вы должны переименовать столбцы в производной таблице.
select latitude from (SELECT lat AS latitude FROM poi_table) p where latitude < 500
Ответ 4
Это будет работать над вашим отредактированным вопросом!
SELECT * FROM (SELECT <Column_List>,
( 6371*1000 * acos( cos( radians(42.3936868308) ) * cos( radians( lat ) ) * cos( radians( lon ) - radians(-72.5277256966) ) + sin( radians(42.3936868308) ) * sin( radians( lat ) ) ) )
AS distance
FROM poi_table) TMP
WHERE distance < 500;
Ответ 5
Порядок логической обработки оператора SELECT
Следующие шаги показывают порядок логической обработки или привязку порядок, для оператора SELECT. Этот порядок определяет, когда объекты определенные на одном этапе, становятся доступными для предложений в последующих шаги. Например, если процессор запросов может связываться с (доступом) таблицы или представления, определенные в предложении FROM, эти объекты и их столбцы становятся доступными для всех последующих этапов. Наоборот, потому что предложение SELECT является шагом 8, любые псевдонимы столбцов или производные столбцы, определенные в этом разделе, не могут быть указаны предыдущими статьи. Однако они могут ссылаться на последующие статьи, такие как предложение ORDER BY. Обратите внимание, что фактическое физическое выполнение оператор определяется процессором запросов, и порядок может меняться из этого списка.
- С
- ON
- JOIN
- WHERE
- GROUP BY
- С CUBE или WITH ROLLUP
- HAVING
- SELECT
- DISTINCT
- ЗАКАЗАТЬ
- TOP
Источник: http://msdn.microsoft.com/en-us/library/ms189499%28v=sql.110%29.aspx
Ответ 6
Оба принятого ответа и Логическая обработка заказа объясняют, почему вы не могли сделать то, что предложили.
Возможное решение:
- использовать производную таблицу (cte/subquery)
- использовать выражение в
WHERE
- создать просмотр/вычисленный столбец
Из SQL Server 2008
вы можете использовать APPLY
оператор в сочетании с Table valued Constructor
:
SELECT *, s.distance
FROM poi_table
CROSS APPLY (VALUES(6371*1000*acos(cos(radians(42.3936868308))*cos(radians(lat))*cos(radians(lon)-radians(-72.5277256966))+sin(radians(42.3936868308))*sin(radians(lat))))) AS s(distance)
WHERE distance < 500;
LiveDemo