2013-02-26 15 views
24

SQL Server用Microsoft OLE DBプロバイダの一部のバージョン(主にWindows XPの場合)がWITHステートメントをサポートしていないことを理解しました。そこで、私はSQL文をテーブル値関数に移動し、それをアプリケーションから呼び出すことにしました。今、私は立ち往生しています。 WITHINSERT INTO声明を使用するにはどうすればよいですか?ここでは、CTE(WITH声明)を省略し、代わりにそのインラインテーブル値関数を作成することができます:-(...SQL Serverのテーブル値関数でCTEステートメントを使用する方法

CREATE FUNCTION GetDistributionTable 
(
    @IntID int, 
    @TestID int, 
    @DateFrom datetime, 
    @DateTo datetime 
) 
RETURNS 
@Table_Var TABLE 
(
    [Count] int, 
    Result float 
) 
AS 
BEGIN 
INSERT INTO @Table_Var ([Count], Result) WITH T(Result) 
    AS (SELECT ROUND(Result - AVG(Result) OVER(), 1) 
     FROM RawResults WHERE IntID = @IntID AND DBTestID = @TestID AND Time >= @DateFrom AND Time <= @DateTo) 
SELECT COUNT(*) AS [Count], 
     Result 
FROM T 
GROUP BY Result 

    RETURN 
END 
GO 

答えて

33

私がこれまでに出ているコードですが、SQL Serverはそれを好きではありませんサブクエリを使用しています。

CREATE FUNCTION GetDistributionTable 
(
    @IntID int, 
    @TestID int, 
    @DateFrom datetime, 
    @DateTo datetime 
) 
RETURNS TABLE 
AS 
RETURN 
(
    SELECT COUNT(*) AS [Count], 
      Result 
    FROM (
       SELECT ROUND(Result - AVG(Result) OVER(), 1) Result 
       FROM RawResults 
       WHERE IntID = @IntID 
       AND DBTestID = @TestID 
       AND Time >= @DateFrom 
       AND Time <= @DateTo  
    ) t 
    GROUP BY 
      Result 
) 
GO 

テーブル値関数におけるCTEのための構文は次のようになります。

CREATE FUNCTION GetDistributionTable 
(
    @IntID int, 
    @TestID int, 
    @DateFrom datetime, 
    @DateTo datetime 
) 
RETURNS TABLE 
AS 
RETURN 
(
    WITH cte AS 
    (
     SELECT ROUND(Result - AVG(Result) OVER(), 1) Result 
     FROM RawResults 
     WHERE IntID = @IntID 
     AND DBTestID = @TestID 
     AND Time >= @DateFrom 
     AND Time <= @DateTo  
    ) 

    SELECT COUNT(*) AS [Count], 
      Result 
    FROM cte 
    GROUP BY 
      Result 
) 
GO 

あなたの例では、選択肢を持っているとき、(挿入を選択)複数ステートメントのTVFを使用しているように見えますお試しください複数ステートメントのTVFは、より良い実行計画を選択する際にクエリオプティマイザを防ぐことができるので、このような(パフォーマンスの差はhereを説明)

+0

をあなたのCTEが再帰的である場合、あなたはおそらく勝ちましたそれをサブクエリ形式に書き直すことができないので、CTE形式は単純な味の問題ではありません。もちろん、再帰的なCTEは、慎重でないとオプティマイザをスローする可能性があります。 MattW

+0

これは、cteのwith部分の前に ';'を使用するために使用されます。 – JJS

14

をインラインTVFを使用して...

CREATE FUNCTION GetDistributionTable 
(
    @IntID int, 
    @TestID int, 
    @DateFrom datetime, 
    @DateTo datetime 
) 
RETURNS 
@Table_Var TABLE 
(
    [Count] int, 
    Result float 
) 
AS 
BEGIN 
    WITH T 
    AS ( 
     select Ticket_Id,COUNT(1) Result from 
     Customer_Survey 
     group by MemberID,SiteId,Ticket_Id 
    ) 
    INSERT INTO @Table_Var ([Count], Result) 
    SELECT COUNT(*) AS [Count], 
     Result 
    FROM T 
    GROUP BY Result 
    RETURN 
END 
GO 
+1

可能であれば、マルチステートメント関数とシングルステートメントの 'RETURNS TABLE'関数の両方をテストする必要があります。後者はインライン展開が可能で、パフォーマンスが向上することがあります(下のリンクを参照してください)。イワンGの答え)。しかし、いつものように、多分*複数のステートメント関数を使用するほうが速いですが*たまに*依存します。 – ErikE

関連する問題