Какие правила следует соблюдать при использовании псевдонимов вместе с подзапросами? - PullRequest
0 голосов
/ 17 марта 2019

Я смущен, увидев эти два фрагмента, один работает, другой нет. Итак, есть одна таблица MyTable с двумя столбцами: ID и Value

Фрагмент 1 (Ошибка)

/*Find the ID that is related to the maximum value*/
SELECT ID
FROM MyTable AS t /*Here MyTable can be a complex subquery. MyTable is just a placeholder here to show you can't use alias t in the subquery after WHERE*/
WHERE Value = (SELECT MAX(Value) FROM t) /*Get error here: 'Invalid object name t"*/

Фрагмент 2 (обработано)

/*Rank Value column*/
SELECT ID, Value,
(SELECT COUNT(Value) FROM MyTable WHERE Value >= t.Value) AS Rank /*No error raised here for t.Value*/
FROM MyTable AS t

Этот пост объясняет, что

Нельзя ссылаться на псевдоним из подзапроса в той же области

Но что такое the same scope? Это объясняет, почему работает фрагмент 2? Я предполагаю, что есть другие возможные способы использования псевдонимов и подзапросов в разных позициях (например, в разных предложениях или в разных местах). Так есть ли общие правила защиты от ошибок, которым нужно следовать при использовании псевдонимов с подзапросами?

(Пожалуйста, не используйте подобные трюки, такие как CTE или обходные пути, такие как TOP и LIMIT)

Ответы [ 2 ]

1 голос
/ 17 марта 2019

Давайте посмотрим на первый запрос.

SELECT ID
FROM MyTable AS t
WHERE Value = (SELECT MAX(Value) FROM t)

Это попытается выбрать из таблицы псевдоним t.
Что не разрешено Следует выбрать из таблицы или представления.

Например:

SELECT ID
FROM MyTable AS t
WHERE Value = (SELECT MAX(Value) FROM MyTable)

Обратите внимание, что это не связано с областью действия. Это также не разрешается без использования каких-либо подзапросов.

Например, это не получится по той же причине

SELECT t1.*, t2.*
FROM MyTable AS t1
JOIN t1 AS t2 ON t2.id = t1.id

Тогда у нас второй запрос.

SELECT ID, Value,
( 
    SELECT COUNT(Value) 
    FROM MyTable t1sub
    WHERE t1sub.Value >= t1out.Value
) AS Rank
FROM MyTable AS t1out

Это называется коррелированным подзапросом.
Этот подзапрос связывает текущий t1out.Value внешнего запроса с таблицей в подзапросе через t1sub.Value.

Повторно выполняет подзапрос для каждой строки из внешнего запроса.

О сфере применения.
Речь идет о том, что часть SQL может смотреть и использовать.

В предыдущем SQL псевдоним t1sub известен только в рамках коррелированного подзапроса.
Внешний запрос даже не знает о псевдониме t1sub, который используется в подзапросе.
Находясь внутри коррелированного подзапроса, можно увидеть и использовать t1out.Value.

Некоторые тесты можно найти на db <> fiddle здесь

1 голос
/ 17 марта 2019

Ваш первый запрос должен работать:

SELECT ID
FROM <tablename> t
WHERE Value = (SELECT MAX(Value) FROM <tablename>) ;

Вы не можете использовать псевдоним для повторного обращения ко всей таблице (я думаю, вы это делали, но в данном примере таблица и псевдоним t).

Вместо этого псевдоним используется для ссылки на столбцы в таблице. Это позволяет связывать столбцы с нужной таблицей, поэтому запрос однозначно выполняет то, что вы собираетесь.

...