Подтвердить что ты не робот

Формула для вычисленного столбца на основе столбца таблицы

Рассмотрим эту таблицу: c_const

 code  |  nvalue
 --------------
 1     |  10000
 2     |  20000  

и другая таблица t_anytable

 rec_id |  s_id  | n_code
 ---------------------
 2      |  x     | 1

Цель состоит в том, чтобы s_id был вычисленным столбцом на основе этой формулы:

 rec_id*(select nvalue from c_const where code=ncode)

Это вызывает ошибку:

Подзапросы в этом контексте запрещены. Разрешены только скалярные выражения.

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

4b9b3361

Ответ 1

Для этого вы можете создать определенную пользователем функцию:

CREATE FUNCTION dbo.GetValue(INT @ncode, INT @recid)
RETURNS INT
AS 
   SELECT @recid * nvalue 
   FROM c_const 
   WHERE code = @ncode

а затем используйте это для определения вычисленного столбца:

ALTER TABLE dbo.YourTable
   ADD NewColumnName AS dbo.GetValue(ncodeValue, recIdValue)

Ответ 2

Это больше похоже на работу для представлений (индексированные представления, если вам нужен быстрый поиск в вычисленном столбце):

CREATE VIEW AnyView
WITH SCHEMABINDING
AS

SELECT a.rec_id, a.s_id, a.n_code, a.rec_id * c.nvalue AS foo
FROM AnyTable a
INNER JOIN C_Const c
    ON c.code = a.n_code

Это имеет незначительное отличие от версии подзапроса в том, что он будет возвращать несколько записей вместо создания ошибки, если для объединения есть несколько результатов. Но это легко решить с помощью ограничения UNIQUE на c_const.code (я подозреваю, что это уже есть PRIMARY KEY).

Это также намного легче понять кому-то, чем версия подзапроса.

Вы можете сделать это с помощью подзапроса и UDF, как показала marc_s, но это может быть очень неэффективно по сравнению с простым JOIN, поскольку скалярный UDF должен быть вычислен по строкам.

Ответ 3

Я сравнил план запроса вида с вычисленным столбцом, вызывающим UDF, который использует тот же запрос, что и представление, и был действительно удивлен, обнаружив, что стоимость вычисляемого столбца была намного меньше (8% против 92%). Я использую SQL Server 2016. Кто-нибудь знает, почему это было бы?

Я понял, что вычисляемый столбец будет по существу запрашивать представление для каждой строки родительской таблицы и будет намного медленнее. Я не работаю с таблицей с большим количеством данных, поэтому просто сравниваю планы запросов, а не фактическое время выполнения.