2011-08-23 135 views
1

我有SQL查詢像SQL批處理查詢處理(SQL查詢輸入數組)

SELECT *, dbo.func(@param1, a.point) as fValue 
FROM dbo.table AS a 
WHERE dbo.func(@param1, a.point) < @param2 

當只執行一次該查詢,一切都很好,但是當我輸入@參數1值的數組讓我們說,超過100個值,執行和提取每個值的結果花費很多時間。

是否有可能的param1 @的數組傳遞到查詢以某種方式,並接收數據集的所有輸入值,而不是執行它爲每個值?

函數func()做一些數學上的2個值。 @param1和a.point是雙精度類型。和,是啊,a.point - 不是ID,並且它不是一個獨特的價值。

我知道,它應該是很容易的,但它看起來像我想的東西。

回答

0

這到底是什麼dbo.func()嗎?是否有可能將100個值插入到表結構中,並且一次對100個集合執行該操作,而不是1x1 100次?

舉個例子,假設你有這樣的功能,只是把一個逗號分隔的浮點值列表變爲單列表:

CREATE FUNCTION dbo.ListFloats 
(
    @List VARCHAR(MAX) 
) 
RETURNS TABLE 
RETURN 
(
    SELECT i = CONVERT(FLOAT, Item) 
    FROM 
    (
     SELECT Item = x.i.value('(./text())[1]', 'FLOAT') 
     FROM 
     (
      SELECT [XML] = CONVERT(XML, '<i>' 
       + REPLACE(@List, ',', '</i><i>') 
       + '</i>').query('.') 
     ) AS a 
     CROSS APPLY 
     [XML].nodes('i') AS x(i) 
    ) AS y 
    WHERE Item IS NOT NULL 
); 
GO 

現在你應該能得到您的花車在一組只是簡單地說:

SELECT i FROM dbo.ListFloats('1.5, 3.0, 2.45, 1.9'); 

採取更進了一步,讓我們說dbo.func()需要這兩個輸入,說是這樣的:

RETURN (SELECT (@param1 + @param2/@param2)); 

現在,我知道你總是被告知模塊化和封裝是好的,但是在內聯函數的情況下,我建議你避免獲得這個結果的函數(同樣你沒有解釋什麼是dbo.func() ,所以我只是猜測這會很容易),並進行內聯。因此,而不是調用dbo.func()的 - 兩次,每次行,沒少 - 你可以說:

DECLARE 
    @Param1Array VARCHAR(MAX) = '1.5, 3.0, 2.45, 1.9', 
    @Param2 FLOAT = 2.0; 

WITH x AS 
(
    SELECT t.point, x.i, fValue = ((x.i + t.point)/t.point) 
    FROM dbo.[table] AS t 
    CROSS JOIN dbo.ListFloats(@Param1Array) AS x 
) 
SELECT point, i, fValue FROM x 
--WHERE fValue < @Param2 
; 

的關鍵是:

  1. 避免單獨處理每個參數。

  2. 避免在單獨的模塊中關閉個別計算。

  3. 儘可能少地執行計算。

如果你不能改變結構這麼多,那麼最起碼,避免計算功能兩次通過寫來代替:

;WITH x AS 
(
    SELECT *, dbo.func(@param1, a.point) as fValue 
    FROM dbo.table AS a 
) 
SELECT * FROM x 
    WHERE fValue < @param2; 

如果你提供有關數據類型的詳細信息,有什麼dbo.func()呢,等等,人們將能夠提供更多切實的建議。

+0

謝謝!這正是我需要的! –

1

你仍然需要執行該功能100倍的每一行,對不對?我在這裏沒有看到任何捷徑。

如果你想要讓他們一下子,你可以做

SELECT dbo.func(@param1, a.point) as fValue1, 
     dbo.func(@param2, a.point) as fValue2 ... 

或類似的東西,但通過他們的循環似乎只是更有效率,我反正。

我想你可以使用遊標檢索每個a.point值一次,然後對其執行100次,但這是很多編碼,並不一定是更簡單的解決方案。

+0

不幸的是,這將不適用於米即我需要獲得整個行以及計算值,如果它在範圍 –

0

你在這張桌子上有沒有索引?如果你在a.point上有一個索引,那麼你將永遠不會使用這個代碼來打它,也就是說總是會進行表掃描。這是關於搜索參數(你可以谷歌這一點)。例如:

如果你有在列xColumn索引表xTable,那麼這樣的:

select colA, colB from xTable where xColumn/2 >= 5 

永遠使用索引,但是這可能會:

select colA, colB from xTable where xColumn >=10 

,所以你可能需要像這樣:

WHERE a.point < Otherfunc(@param1, @param2)