Sql server SQL:将单行中的列值连接成以逗号分隔的字符串

Sql server SQL:将单行中的列值连接成以逗号分隔的字符串,sql-server,tsql,string-concatenation,Sql Server,Tsql,String Concatenation,假设我在SQL Server中有这样一个表: Id City Province Country 1 Vancouver British Columbia Canada 2 New York null null 3 null Adama null 4 null null

假设我在SQL Server中有这样一个表:

Id    City           Province             Country
1     Vancouver      British Columbia     Canada
2     New York       null                 null
3     null           Adama                null
4     null           null                 France
5     Winnepeg       Manitoba             null
6     null           Quebec               Canada
7     Seattle        null                 USA 
如何获得查询结果,使位置是由“,”分隔的城市、省和国家的串联,并省略空值。我希望确保没有任何尾随逗号、前置逗号或空字符串。例如:

Id    Location
1     Vancouver, British Columbia, Canada
2     New York
3     Adama
4     France
5     Winnepeg, Manitoba
6     Quebec, Canada
7     Seattle, USA
这里有一个选项:

SELECT (CASE WHEN City IS NULL THEN '' ELSE City + ', ' END) + 
(CASE WHEN Province IS NULL THEN '' ELSE Province + ', ' END) +
(CASE WHEN Country IS NULL THEN '' ELSE Country END) AS LOCATION
FROM MYTABLE

这是一个难题,因为逗号必须介于以下两者之间:

select id, coalesce(city+', ', '')+coalesce(province+', ', '')+coalesce(country, '')
from t
看起来它应该可以工作,但是我们可以在结尾处得到一个无关的逗号,比如当country为NULL时。所以,它需要更复杂一点:

select id,
       (case when right(val, 2) = ', ' then left(val, len(val) - 1)
             else val
        end) as val
from (select id, coalesce(city+', ', '')+coalesce(province+', ', '')+coalesce(country, '') as val
      from t
     ) t

如果没有很多中间逻辑,我认为最简单的方法是在每个元素中添加一个逗号,然后在末尾删除任何多余的逗号。

丑陋,但它适用于MS SQL:

select Id ,   
 Coalesce( City + ',' +Province + ',' + Country,
           City+ ',' + Province,
           Province + ',' + Country,
           City+ ',' + Country,
           City,
           Province,
           Country
          ) as location
from table
    select
    id,
    case
        when right(rtrim(coalesce(city + ', ','') + coalesce(province + ', ','') + coalesce(country,'')),1)=',' then left(rtrim(coalesce(city + ', ','') + coalesce(province + ', ','') + coalesce(country,'')),LEN(rtrim(coalesce(city + ', ','') + coalesce(province + ', ','') + coalesce(country,'')))-1)
        else rtrim(coalesce(city + ', ','') + coalesce(province + ', ','') + coalesce(country,''))
    end
from
    table
使用“+”运算符

请理解null值不适用于“+”运算符(例如:“Winnepeg”+null=null),因此请确保使用ISNULL()或COALESCE()函数将null替换为空字符串,例如:ISNULL('Winnepeg',''))+ISNULL(null.)

此外,如果您的一个collumn可能被解释为一个数字,那么一定要使用CAST()函数,以避免返回错误,例如:CAST('Winnepeg'as varchar(100))

到目前为止,大多数示例都忽略了其中的一个或多个部分。此外,有些示例使用子查询或执行长度检查,这是您确实不应该做的——只是不必要——但如果这样做,优化器可能会节省您的时间


祝你好运

我认为这解决了我在其他答案中发现的所有问题。无需测试输出的长度或检查前导字符是否为逗号,无需担心连接非字符串类型,无需在不可避免地添加其他列(如邮政编码)时显著增加复杂性

DECLARE @x TABLE(Id INT, City VARCHAR(32), Province VARCHAR(32), Country VARCHAR(32));

INSERT @x(Id, City, Province, Country) VALUES
(1,'Vancouver','British Columbia','Canada'),
(2,'New York' , null             , null   ),
(3, null      ,'Adama'           , null   ),
(4, null      , null             ,'France'),
(5,'Winnepeg' ,'Manitoba'        , null   ),
(6, null      ,'Quebec'          ,'Canada'),
(7,'Seattle'  , null             ,'USA'   );

SELECT Id, Location = STUFF(
      COALESCE(', ' + RTRIM(City),     '') 
    + COALESCE(', ' + RTRIM(Province), '') 
    + COALESCE(', ' + RTRIM(Country),  '')
    , 1, 2, '')
  FROM @x;


SQL Server 2012添加了一个新的T-SQL函数,名为,但在这里它没有用处,因为您仍然需要在发现的值之间选择性地包含逗号,并且没有工具可以做到这一点-它只是将值组合在一起,没有分隔符选项。这避免了对非字符串类型的担心,但不允许您非常优雅地处理空值与非空值。

Oops。。。删除了我的错误答案。。。没有仔细阅读enough@AaronBertrand,你能给我指一下副本吗?我花了相当多的时间来寻找答案,但没有找到任何答案。@SQLQUALL好奇的是,我尝试了很多东西,但惊讶的是,这比我想象的要困难得多。在另一种语言中,我只会使用类似于Array.Join(Array,“,”)的东西,但在SQL中找不到任何类似的东西。你的评论让我相信你认为这是微不足道的,所以你能提供你的答案吗?这里有一个:谢谢@Aaronbertrand如果City为空,你会得到
,加拿大魁北克省
。我不需要前面的逗号。更新为考虑空cityStill后会留下逗号,例如
马尼托巴省温尼伯市,
请注意,CONCAT\u NULL\u YIELDS\u NULL应设置为enabled以使其工作。解决这个问题的方法很好。我觉得这一点都不优雅。如果有5列、9列或15列呢?你真的要列出所有可能的组合?我真的同意@AaronBertrand,我的解决方案可以解决这个问题,但它的扩展性不好。他在问题下的评论中链接到的公认答案效果更好。当列数更多时,这将导致问题,并且这里有7个左右的三列组合检查,如果列数没有增加怎么办……这将产生例如
New Yor
Winnipeg,Manitob
。哎呀,SQL Server忽略字符串末尾的空格。因此“-2”也删除了最后一个字符。我把它改为“-1”。它仍然是不必要的复杂(至少是IMHO)。你认为这里需要子查询还是需要检查尾随字符?对我来说,这种逻辑比你的版本更容易理解,因为逗号自然出现在单词后面,而不是单词前面。除此之外,它们基本上是一样的(我以前确实考虑过用逗号,但在我看来很尴尬)。你的优点是,你不需要知道逗号在哪里,因为它总是在开头。我认为,为了在列名后加逗号而引入子查询是不必要的复杂性。这没有错,但它非常复杂。还要考虑凯文的回答在有4, 5或6列时会有多复杂。+ 1,这是除了我之外的唯一答案,我可以同意,不幸的是你没有包含任何代码。这真的帮了我很大的忙,谢谢-我还需要一个空字符串检查,使用
NULLIF
,所以:
SELECT Id,Location=STUFF(COALESCE(','+RTRIM(NULLIF(City),),''),')+COALESCE(','+RTRIM(NULLIF(Province),),')+COALESCE(','+RTRIM)(如果为空,则从@x;