2011-08-23 117 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)