0

レポートのために5分ごとに実行する必要がある、長くて非常に反復的なクエリがあります。以下のselectステートメントの1つからの抜粋がいくつかあります。これに類似した、26の列があります。時間枠、ジョブ、および演算子に基づいて、それぞれが7つの異なるwhereステートメントを持つ合計6つの異なる行で実行されるため、大量のT-SQLを作成するのではなく、5分ごとに実行することを考えていました。 2桁の行番号(以下の例では「05」)、where条件、および列のID(以下の例では「ジョブ」)のパラメーターが渡されたストアード・プロシージャーを作成します。私が抱えている問題は、selectステートメント内の列名を連結することです。私はいくつかの方法を試しましたが、どれもうまくいきませんでした。

例(はい、10進数としてキャストすることはたくさん知っています。すべてがvarcharであることを自分に言い聞かせたいのですが、データを製造マシンからDbに転送するアプリケーションは、タイムスタンプの文字列または日時としてのみ書き込みます。charindexは次のようになります。データが小数点以下20桁に配置されているのを見たので、まれにそれ以上になります)

    ,AVG(CAST(LEFT("E05UP", (CHARINDEX(',', E05UP, 5) + 6)) AS decimal(11,6)))*100 AS JobE05Up
        ,AVG(CAST(LEFT(E05QUAL, (CHARINDEX(',', E05QUAL, 5) + 6)) AS decimal(11,6)))*100 AS JobE05Qual
        ,CASE WHEN AVG(CAST(LEFT(E05UP, (CHARINDEX(',', E05UP, 5) + 6)) AS decimal(11,6)))>0 AND AVG(CAST(LEFT(E05SPD, (CHARINDEX(',', E05SPD, 5) + 6)) AS decimal(11,6)))>0 AND 
            AVG(CAST(LEFT(E05QUAL, (CHARINDEX(',', E05QUAL, 5) + 6)) AS decimal(11,6)))>0 THEN (AVG(CAST(LEFT(E05UP, (CHARINDEX(',', E05UP, 5) + 6)) AS decimal(11,6)))*
            (AVG(CAST(LEFT(E05SPD, (CHARINDEX(',', E05Spd, 5) + 6)) AS decimal(11,6)))/@E05SpeedMAX)*AVG(CAST(LEFT(E05QUAL, (CHARINDEX(',', E05QUAL, 5) + 6)) AS decimal(11,6)))*100)
            ELSE 0 END AS JobE05OEE

そして、私が簡単にやろうとしていることは次のとおりです。

    SELECT AVG(E+@P1+SPD) AS @P2+Speed FROM Test.Dbo.Line+@P1 WHERE @P3

編集:最後のDb書き込みからのみデータを選択するクエリ全体。すべてのキャストを関数に変更した後、このレポートの他のすべてのクエリとの間で変更されるのは、行番号(L05)、列名、 where句、および複数の行を処理するため、合計または平均化される数値。

DECLARE @L05CurWO as INT
DECLARE @L05CurCount AS INT
DECLARE @L05SpeedMAX AS INT
DECLARE @E05SpeedMAX AS INT
DECLARE @H05SpeedMAX AS INT
DECLARE @P05SpeedMAX AS INT
DECLARE @C05SpeedMAX AS INT
DECLARE @L05CurQual AS Decimal(11,6)

--Set Maximum Line Speeds Speeds
SET @L05SpeedMAX = 147
SET @E05SpeedMAX = 147
SET @H05SpeedMAX = 147
SET @P05SpeedMAX = 147
SET @C05SpeedMAX = 147


SET @L05CurWO = (SELECT TOP 1 L05WO FROM WB.dbo.Line05 WHERE L05WO IS NOT NULL ORDER BY L05Time DESC)
SET @L05CurCount = (SELECT SUM(dbo.TOD(E05Count)) FROM WB.dbo.Line05 WHERE L05WO = @L05CurWO)
SET @L05CurQual = (SELECT TOP 1 CASE WHEN dbo.TOD(L05Count)<1 THEN 0 ELSE CASE WHEN dbo.TOD(L05Blowoff)<1 THEN 1 ELSE (1-(dbo.TOD(L05Blowoff)/
                        dbo.TOD(L05Count))) END END FROM WB.dbo.Line05 WHERE L05WO = @L05CurWO ORDER BY L05Time DESC)


--Select Current Numbers
    SELECT TOP 1 @L05CurWO AS CurrentL05WorkOrder
                    ,L05TE AS CurrentL05TE
                    ,L05TF AS CurrentL05TF
                    ,@L05CurCount AS CurrentL05Count
                    ,@L05JobScrap AS CurrentL05Scrap
                    ,L05QUAN AS CurrentL05Quantity
                    ,dbo.TOD(L05UP)*100 AS CurrentL05Uptime
                    ,dbo.TOD(C05SPD) AS CurrentL05Speed
                    ,@L05CurQual*100 AS CurrentL05Qual
                    ,CASE WHEN dbo.ToD(L05UP)>0 AND dbo.ToD(C05SPD)>0 AND @L05CurQUAL>0 THEN dbo.ToD(L05UP)*(dbo.ToD(C05SPD)/@L05SpeedMAX)*@L05CurQual ELSE 0 END AS CurrentL05OEE
                    ,dbo.ToD(E05SPD) AS CurrentE05Speed
                    ,dbo.ToD(E05UP)*100 AS CurrentE05Up
                    ,dbo.ToD(E05QUAL)*100 AS CurrentE05Qual
                    ,CASE WHEN dbo.ToD(E05UP)>0 AND dbo.ToD(E05SPD)>0 AND dbo.ToD(E05QUAL)>0 THEN (dbo.ToD(E05UP)*(dbo.ToD(E05SPD)/@E05SpeedMAX)*(1-(dbo.ToD(E05Blowoff)/
                     dbo.ToD(E05Count)))*100) ELSE 0 END AS CurrentE05OEE
                    ,dbo.ToD(H05SPD) AS CurrentH05Speed
                    ,dbo.ToD(H05UP)*100 AS CurrentH05Up
                    ,dbo.ToD(H05QUAL)*100 AS CurrentH05Qual
                    ,CASE WHEN dbo.ToD(H05UP)>0 AND dbo.ToD(H05SPD)>0 AND dbo.ToD(H05QUAL)>0 THEN (dbo.ToD(H05UP)*(dbo.ToD(H05SPD)/@H05SpeedMAX)*(1-(dbo.ToD(H05Blowoff)/
                     dbo.ToD(H05Count)))*100) ELSE 0 END AS CurrentH05OEE
                    ,dbo.ToD(P05SPD) AS CurrentP05Speed
                    ,dbo.ToD(P05UP)*100 AS CurrentP05Up
                    ,dbo.ToD(P05QUAL)*100 AS CurrentP05Qual
                    ,CASE WHEN dbo.ToD(P05UP)>0 AND dbo.ToD(P05SPD)>0 AND dbo.ToD(P05QUAL)>0 THEN (dbo.ToD(P05UP)*(dbo.ToD(P05SPD)/@P05SpeedMAX)*(1-(dbo.ToD(P05Blowoff)/
                     dbo.ToD(P05Count)))*100) ELSE 0 END AS CurrentP05OEE
                    ,dbo.ToD(C05SPD) AS CurrentC05Speed
                    ,dbo.ToD(C05UP)*100 AS CurrentC05Up
                    ,dbo.ToD(C05QUAL)*100 AS CurrentE05Qual
                    ,CASE WHEN dbo.ToD(C05UP)>0 AND dbo.ToD(C05SPD)>0 AND dbo.ToD(C05QUAL)>0 THEN (dbo.ToD(C05UP)*(dbo.ToD(C05SPD)/@P05SpeedMAX)*(1-(dbo.ToD(C05Blowoff)/
                     dbo.ToD(C05Count)))*100) ELSE 0 END AS CurrentC05OEE
    FROM WB.dbo.Line05
    WHERE L05WO = @L05CurWO
    ORDER BY L05Time DESC
4

1 に答える 1

2

皮切りに

Create Function dbo.ToD(@val as varchar(max)) Returns Decimal(11, 6) As
Begin
  Return Cast(Left(@val, (CharIndex(',', @val, 5) + 6)) As Decimal(11, 6))
End

次のステップは動的SQLだと思います。このようなもので、正しい軌道に乗ることができます。(@Colがユーザー入力からのものである場合、これにはSQLインジェクションの脆弱性があります):

これは完全にテストされていないため、ばかげたエラーが発生します。また、クエリごとにどのビットが変更され、どのビットが同じままであるかを正確に誤解した可能性があります。動的SQLを介してパラメーターを設定するメカニズムが機能するかどうかは100%わかりませんが、sp_executesqlの結果を変数に取り込む方法を読んでいます。。代わりに一時テーブルを使用する必要がある場合があります。

Declare 
  @Col nvarchar(max) = '05',
  @sql nvarchar(max),
  @params nvarchar(max),
  @CurWO int

-- Dynamically getting one of the current values
Set @sql = N'Set @CurWO = (' + 
           N'Select Top 1 L' + @Col + N'WO' +
           N' From WB.dbo.Line' + @Col + 
           N' Where L' + @Col + N'WO Is Not Null' +
           N' Order By L' + @Col + N'Time Desc)'

-- For diagnosing the inevitable errors
Print @sql

Set @params = N'@CurWO int output'

Exec sp_executesql @sql, @params, @CurWO Output

-- Dynamically executing the main query
Set @sql = N'Select Top 1 @CurWO As CurrentL' + @Col + N'WorkOrder,' + -- @CurWO from last query
           N' L' + @Col + N'TE AS CurrentL' + @Col + N'TE,' +
           N' L' + @Col + N'TF AS CurrentL' + @Col + N'TF,' +
           ...
           N' From WB.dbo.Line' + @Col +
           N' Where L' + @Col + N'WO = @CurWO' +
           N' Order By L' + @Col + N'Time Desc'

-- For diagnosing the inevitable errors
Print @sql

Set @params = N'@CurWO int'

Exec sp_executesql @sql, @params, @CurWO
于 2012-11-13T15:19:48.070 に答える