【问题标题】:SQL Query return results in a comma separated string (Optimised)SQL 查询以逗号分隔的字符串返回结果(优化)
【发布时间】:2012-05-11 06:21:15
【问题描述】:

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

我已经阅读了 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。

任何想法如何优化这个逻辑? 非常感谢提前

【问题讨论】:

  • 您使用的是什么 RDBMS 和版本?

标签: sql string stored-procedures coalesce sql-function


【解决方案1】:

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

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

所以,除了确保您的连接列(id、SomeId)被编入索引之外,我不确定您是否可以对此进行优化。

【讨论】:

    【解决方案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)。

    【讨论】:

      【解决方案3】:

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

      KM 指出我的方法存在缺陷,并提供了一个更好的解决方案 here 的链接,同样的逻辑仍然适用,但是 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-10-25
        • 1970-01-01
        • 2018-10-05
        • 2019-10-04
        • 1970-01-01
        • 2017-02-03
        相关资源
        最近更新 更多