2012-11-13 168 views
0

我有一個很長且非常重複的查詢,我需要每5分鐘運行一次報表,有一些摘錄來自在下面的選擇語句中,我有26列與此類似,需要根據時間範圍,作業和運算符對總共6行不同的行進行運行,每行都有7個不同的where語句,而不是創建一個大量的T-SQL,並運行它每隔五分鐘我想創建一個存儲過程與參數傳遞給它的兩位數行號(在下面的例子'05'),where條件和一個列的標識符(在'Job'下面的例子中)。我遇到的問題是連接select語句內部的列名,我嘗試了許多方法,但都沒有工作。SQL使用一個字符串在一個選擇語句中的一個字符串連接一個變量

示例(是的,我知道很多鑄件都是十進制的,我想對自己嚷嚷一切都是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([email protected]+SPD) AS @P2+Speed FROM [email protected] WHERE @P3 

編輯:整個查詢從最後一個Db中選擇數據只寫,在將所有Casts更改爲函數之後,在此報表與此報表的每個其他查詢之間唯一會改變的是行號(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 

回答

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注入漏洞):

這是完全未經測試的,所以會有愚蠢的錯誤。我也可能錯誤地理解了哪些位從查詢改變爲查詢,哪些位保持不變。我不是100%確定通過動態sql設置參數的機制,但我在How to get sp_executesql result into a variable?上閱讀它。您可能需要使用臨時表。

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 
+0

我已經創建了一個JD Edwards當前日期轉換一側的日期函數,不知道爲什麼我也沒有想到這一點......謝謝! – motoxrdr21

+0

一旦你有了這個,把重寫的查詢,我們可以看看進一步簡化。 – Laurence

+0

謝謝,看上面的編輯。 – motoxrdr21

相關問題