web-dev-qa-db-ja.com

SQLサーバーはCTEとして一時関数を作成します

より大きなクエリで使用するためにtemp関数を作成する必要がありますが、データベースに対する作成権限がありません(#TEMPテーブルを除く)。

この目的でCTEまたは#tempクエリを使用できる方法はありますか?たぶん、ここには本当に簡単なものが欠けています。

例(どのように見えるか):-

with add1(x) as
  return x+1

select add1(v.Value1), add1(v.Value2)
from Values v

値の表

Id Value1 Value2
1  1       4
2  2       5
3  3       6

編集

Aaron Bertrandの回答に従って、なんとか機能させることができました。

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

最後のPIVOTは結果をめちゃくちゃにしています。なぜそれが必要なのかと思っていました。

UNPIVOTPIVOTのさまざまな部分に頭を悩ませています。


EDIT2

私の答えを見てください、
列だけを処理するだけで動作します。

4
heyNow

関数を作成せずにこの種のコードを複製するには:

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);

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);

関数が非常に複雑で、繰り返したくない場合、それが実際の問題である場合は、この解決策を試すことができます。複雑ですが、関数を1回だけ作成できます。これを3列以上に拡張する必要がある場合は、さらに複雑になります。

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;

または、どこかに関数を作成するための権限を要求することもできます。

5
Aaron Bertrand

実際の質問を散らかすのではなく、答えにさらに力を入れています。

Aaron Bertrand'sの回答のおかげで上達できたので、それを回答としてマークしました。
この質問を読んでいる人は、より多くの文脈を得るために最初にそれを見る必要があります。

そのローカル関数を使用して処理する必要がある列が1つだけの場合、UNPIVOTPIVOTは実際には必要なく、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
1
heyNow