J'ai besoin de créer une fonction temporaire, pour une utilisation dans une requête plus importante, mais je n'ai pas d'autorisations de création sur la base de données (sauf pour les tables #TEMP).
Existe-t-il un moyen d'utiliser un CTE ou une requête #temp à cette fin? Peut-être que je manque quelque chose de vraiment simple ici.
Exemple (à quoi il pourrait ressembler): -
with add1(x) as
return x+1
select add1(v.Value1), add1(v.Value2)
from Values v
Tableau des valeurs
Id Value1 Value2
1 1 4
2 2 5
3 3 6
Selon la réponse d'Aaron Bertrand, j'ai réussi à faire fonctionner quelque chose.
CREATE TABLE #myTempTable
(
id int identity(1,1) primary key,
amount int,
col1 varchar(10),
col2 varchar(4)
);
-- quite a few more cols in my actual temp table,
-- omitted to show the real issue
INSERT #myTempTable(amount,col1, col2) VALUES(10,'a1', 'b1'),(15,'a2','b2');
;WITH processed AS
(
SELECT * FROM #myTempTable AS r
UNPIVOT (Result FOR [Value] IN r.Amount) unp
CROSS APPLY
(
/******** COMPLEX FUNCTION HERE ********/
/**** Applies to output of unpivot *****/
SELECT unp.Result + 10 [Processed_amount]
) AS a
--PIVOT (max(orig) FOR Value IN ( amount)) AS p2
)
select top 10 [Processed_amount], * from processed
Le dernier PIVOT
gâche cependant les résultats. Je me demandais pourquoi cela était nécessaire.
J'essaie toujours d'enrouler ma tête autour des différentes parties de UNPIVOT
et PIVOT
.
Veuillez voir ma réponse,
Je l'ai fait fonctionner où nous n'avons besoin que d'une colonne à traiter ..
Pour répliquer ce type de code, sans créer de fonction:
CREATE FUNCTION dbo.add1(@x int)
RETURNS int
AS
BEGIN
RETURN (SELECT @x + 1);
END
GO
SELECT dbo.add1(v.Value1), dbo.add1(v.Value2)
FROM (VALUES(1,2),(3,4)) AS v(Value1, Value2);
Vous pouvez utiliser CROSS APPLY
:
SELECT z.v1, z.v2
FROM (VALUES(1,2),(3,4)) AS v(Value1, Value2)
CROSS APPLY
(
SELECT v.Value1 + 1, v.Value2 + 1
) AS z(v1,v2);
Si la fonction est extrêmement compliquée et que vous ne voulez pas la répéter, et c'est le problème réel, vous pouvez essayer cette solution. Il est complexe mais vous permet de n'écrire la fonction qu'une seule fois. Si vous devez l'étendre à plus de deux colonnes, cela devient plus compliqué.
CREATE TABLE #vals
(
id int identity(1,1) primary key,
a int,
b int
);
INSERT #vals(a,b) VALUES(1,2),(15,16);
;WITH vals AS
(
SELECT * FROM #vals AS v
UNPIVOT (Result FOR [Value] IN (a,b)) unp
CROSS APPLY
(
/******** COMPLEX FUNCTION HERE ********/
/**** Applies to output of unpivot *****/
SELECT unp.Result + 10
) AS new(orig)
PIVOT (MAX(orig) FOR Value IN ([a],[b])) AS p2
)
SELECT v1.id,
OriginalValue1 = v1.Result,
Value1 = v1.a,
OriginalValue2 = v2.Result,
Value2 = v2.b
FROM vals AS v1
JOIN vals AS v2 ON v1.id = v2.id
AND v1.a IS NOT NULL
AND v2.b IS NOT NULL;
GO
DROP TABLE #vals;
Ou vous pouvez demander les autorisations pour créer votre fonction quelque part.
Je mets plus de travail dans une réponse au lieu d'encombrer la vraie question ..
J'ai pu progresser grâce à Aaron Bertrand's
réponse, donc je l'ai marqué comme réponse.
.
Il s'avère que si une seule colonne est nécessaire pour être traitée à l'aide de cette fonction locale, nous n'avons pas réellement besoin de UNPIVOT
et PIVOT
et pouvons gérer avec juste un CROSS APPLY
CREATE TABLE #myTempTable
(
id int identity(1,1) primary key,
Amount int,
Col1 varchar(10),
Col2 varchar(4)
);
-- quite a few more cols in my actual temp table,
-- omitted to show the real issue
INSERT #myTempTable(Amount,Col1, Col2) VALUES(10,'a1', 'b1'),(15,'a2','b2');
;WITH p AS
(
SELECT * FROM #myTempTable AS q
CROSS APPLY
(
/******** COMPLEX FUNCTION HERE ********/
/**** Applies to output of unpivot *****/
SELECT q.Amount + 10 [Processed_amount]
) AS r
)
select top 10 [Processed_amount], * from p