1

我想运行一个存储过程,它返回一大堆东西,其中一个是逗号分隔的结果字符串。

我已经阅读了 COALESCE 并创建了一个这样的函数:

DECLARE @ListOfStuff NVARCHAR(4000)

SELECT  @ListOfStuff = COALESCE(@ListOfStuff + ', ', '') + Z.SingleStuff
FROM    X 
INNER JOIN Y ON X.SomeId = Y.Id
INNER JOIN Z ON Y.SomeId = Z.id
WHERE --Some condition

RETURN ISNULL(@ListOfStuff, '')

然后在我的主 SELECT 中调用这个函数,它按预期工作。但是,该过程现在需要很长时间才能运行并且经常超时。我想知道的是,是否有人知道如何优化它。我相信摆脱该功能并将此逻辑合并到过程中将使它运行得更快,但我无法找到一种方法来拥有以这种方式使用 COALESCE 的子选择。

任何想法如何优化这个逻辑?提前谢谢了

4

3 回答 3

2

您可以通过将 @ListOfStuff 声明为 '' 来完全取消 COALESCE,然后稍微不同地处理字符串连接和最终返回值。就目前而言,您正在对每一行进行评估。

DECLARE @ListOfStuff NVARCHAR(4000) = ''

SELECT  @ListOfStuff = @ListOfStuff + Z.SingleStuff + ','
FROM    X 
INNER JOIN Y ON X.SomeId = Y.Id
INNER JOIN Z ON Y.SomeId = Z.id
WHERE --Some condition

IF LEN(@ListOfStuff) > 0
BEGIN
    SELECT @ListOfStuff = LEFT(@ListOfStuff, LEN(@ListOfStuff) - 1)
END
RETURN @ListOfStuff

可能的优化是确保连接中使用的所有列都有索引,如果您可以使用 varchar 而不是 nvarchar(当然取决于 z.SingleStuff 的内容和数据类型),这可能会有所帮助。但是我不确定如果不对调用它的存储过程进行可能的重大修改,您还能做什么。

如果要为 SELECT 的每一行调用此函数,那么您可能对表值函数或 CROSS APPLY 有一些运气(取决于您如何使用它,以及您的 RDBMS)。

于 2012-05-01T21:19:53.547 回答
0

COALESCE 并没有真正在这里做工作(它只是整理空值 - 请参阅http://msdn.microsoft.com/en-us/library/ms190349.aspx

使用逗号连接值是使用@ListOfStuff 变量完成的,并且确实似乎是一种很好的(唯一的?)方法,即如果你摆脱了这个函数,你仍然需要这样做在您的存储过程中。拥有一个函数本身不应导致您看到的性能下降。

所以,除了确保您的连接列(id,SomeId)被索引之外,我不确定您是否可以优化它。

于 2012-05-01T21:00:55.033 回答
0

在没有看到您的 SP 的情况下,我无法提出实际可行的解决方案,但是如果您使用 SQL-Server,您可以使用该FOR XML PATH方法,该方法在 SO 的许多问题中都有体现。我最近回答了一个问题,打破了这种方法背后的逻辑。我更喜欢这种方法而不是函数方法,因为函数偏离了首选的基于集合的 SQL 方法。

KM指出了我的方法的一个缺陷,并在此处提供了一个更好的解决方案的链接,同样的逻辑仍然适用,但是 KM 避免了文本中出现保留字符以进行连接的问题。

我对您正在寻找的解决方案的最佳猜测如下:

SELECT  X.SomeColumn,
        Y.SomeColumn,
        STUFF(( SELECT  ', ' + Z.SingleStuff
                FROM    Z
                WHERE   Z.ID = Y.SomeID
                FOR XML PATH(''), TYPE
            ).Value('.', 'VARCHAR(MAX)'), 1, 2, '') [ListOfStuff]
FROM    X 
        INNER JOIN Y 
            ON X.SomeId = Y.Id
WHERE --Some condition
于 2012-05-03T09:56:34.960 回答