web-dev-qa-db-fra.com

formule pour la colonne calculée basée sur la colonne de la table différente

Considérez ce tableau: c_const

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

et une autre table t_anytable

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

Le but est d'avoir s_id être une colonne calculée, basée sur cette formule:

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

Cela produit une erreur:

Les sous-requêtes ne sont pas autorisées dans ce contexte. Seules les expressions scalaires sont autorisées.

Comment puis-je calculer la valeur de cette colonne calculée en utilisant la colonne d'une autre table comme entrée?

46

Vous pouvez créer une fonction définie par l'utilisateur pour cela:

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

puis utilisez-le pour définir votre colonne calculée:

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

Cela semble être plus un travail pour les vues (vues indexées, si vous avez besoin de recherches rapides sur la colonne calculée):

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

Cela présente une différence subtile par rapport à la version de sous-requête en ce sens qu'elle retournerait plusieurs enregistrements au lieu de produire une erreur s'il y a plusieurs résultats pour la jointure. Mais cela est facilement résolu avec une contrainte UNIQUE sur c_const.code (Je soupçonne que c'est déjà un PRIMARY KEY).

C'est aussi beaucoup plus facile à comprendre pour quelqu'un que la version de sous-requête.

Vous pouvez le faire avec une sous-requête et une UDF comme l'a montré marc_s, mais cela risque d'être fortement inefficace par rapport à un simple JOIN, car une UDF scalaire devra être calculée en ligne- par rangée.

24
Aaronaught