【问题标题】:t-sql how does this work? SELECT @MyList = ISNULL(@MyList,'') + Title + ', ' FROM Titlest-sql 这是如何工作的? SELECT @MyList = ISNULL(@MyList,'') + Title + ',' FROM Titles
【发布时间】:2011-12-11 02:14:09
【问题描述】:

我遇到了一些非常酷的 t-sql,它可以从一个 t-sql 查询中的选定行生成一个以逗号分隔的列值列表:

SELECT @MyList = ISNULL(@MyList,'')  + Title + ', ' FROM Titles

但我不知道它是如何工作的。不知何故,它必须进行递归调用,但我不知道如何。 任何人都可以向我解释或给我发送一个解释它的链接吗? 要查看它是否有效,请使用以下脚本:

CREATE TABLE  Titles(
    Title varchar(50)  
    )

    insert Titles  values ( 'Doctor')
    insert Titles   values ( 'Nurse')
    insert Titles   values ( 'Administrator')
    insert Titles   values ( 'CMA')

    select * from Titles

    DECLARE @MyList VARCHAR(1000)
    SET @MyList = ''
    SELECT @MyList = ISNULL(@MyList,'')  + Title + ', ' FROM Titles
    SELECT @MyList

【问题讨论】:

  • 想象一下数据库引擎遍历Titles 的每一行。如果它为每一行执行@MyList = ... 赋值,@MyList 最终会得到什么值?这里没有递归。
  • 不是一个真正的答案,但我可以建议另一种方法吗? SELECT STUFF(( SELECT ',' + Title FROM Titles t FOR XML PATH('') ), 1, 1, '')。它不需要变量声明,因此可以在单个查询中使用。
  • 您可能会在使用此方法时遇到问题,尤其是在您按计算结果排序时。 The correct behaviour for an aggregate concatenation query is undefined.

标签: sql tsql recursion


【解决方案1】:

任务:

@MyList = ISNULL(@MyList,'')  + Title + ', ' 

对 Titles 表的每一行进行评估。它将每一行的Title 列值连接到@MyList。

只需要测试ISNULL(@MyList,''),以便@MyList 以空字符串开头,如果它是NULL。在您的示例中,ISNULL 是不必要的,因为 @MyList 已明确设置为空字符串。

【讨论】:

    【解决方案2】:

    Titles包含一组预定义的标题,所以查询

    SELECT @MyList = ISNULL(@MyList,'')  + Title + ', ' FROM Titles 
    

    是否为表Titles 中的每一行附加标题列的值

    这相当于下面的循环:

    // Actually  ISNULL(@MyList,'') does initialize 
    // @MyList by empty string whilst processing the first row in tsql query
    string myList = "";
    foreach(string title in Titles)
    {
       myList = myList +  ', ' + title;
    }
    

    【讨论】:

      【解决方案3】:

      其他答案已经解释了为什么这会建立您的逗号分隔列表。您会注意到最后有一个额外的逗号,如果您愿意,您可以在之后删除它。如果您使用的是 SQL Server 2005 或更高版本,则可以使用 COALESCE 并且不使用逗号结尾:

      SELECT @MyList = COALESCE(@MyList + ', ','') + Title FROM Titles 
      

      对于第一行,@MyList 将是 NULL,因此 @MyList + ', ' 将评估为 NULL 并且 COALESCE 将返回 ''。本质上,处理第一行是这样的:

      SELECT @MyList = '' + Title

      对于后续行,COALESCE 将返回 @MyList + ', ',您将获得等价于

      SELECT @MyList = @MyList + ', ' + Title.

      【讨论】:

      • COALESCE 在这里没有做任何神奇的事情。真正的区别是您在数据之前而不是之后附加逗号。在查询中使用 ISNULL 会产生相同的结果。您还提到您需要 SQL2005 或更高版本。这不是真的。我知道这段代码适用于 SQL2000,但它可能也适用于早期版本。
      猜你喜欢
      • 2023-02-24
      • 2015-08-16
      • 1970-01-01
      • 2020-05-17
      • 2011-01-08
      • 2015-12-09
      • 2013-05-08
      • 2019-05-03
      • 1970-01-01
      相关资源
      最近更新 更多