В SQL: конкатенация значений столбцов в одной строке в строку через запятую

предположим, у меня есть такая таблица в 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

6 ответов


Я думаю, что это позаботится обо всех проблемах, которые я заметил в других ответах. Нет необходимости проверять длину вывода или проверять, является ли ведущий символ запятой, не беспокоиться о конкатенации нестроковых типов, не значительно усложняется, когда неизбежно добавляются другие столбцы (например, почтовый индекс)...

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 с именем CONCAT, но это не полезно здесь, так как вы все равно должны дополнительно включать запятые между обнаруженными значениями, и нет возможности сделать это - он просто munges значения вместе без опции для разделителя. Это позволяет избежать необходимости беспокоиться о нестроковых типах, но не позволяет обрабатывать нули против не-нулей очень элегантно.


select Id ,   
 Coalesce( City + ',' +Province + ',' + Country,
           City+ ',' + Province,
           Province + ',' + Country,
           City+ ',' + Country,
           City,
           Province,
           Country
          ) as location
from table

это сложная проблема, потому что запятые должны идти между:

select id, coalesce(city+', ', '')+coalesce(province+', ', '')+coalesce(country, '')
from t

Кажется, что это должно работать, но мы можем получить постороннюю запятую в конце, например, когда страна равна нулю. Итак, это должно быть немного сложнее:

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

без большой промежуточной логики я думаю, что самый простой способ-добавить запятую к каждому элементу, а затем удалить любую постороннюю запятую в конце.


использовать оператор'+'.

поймите, что значения null не работают с оператором ' + '(например:' Winnepeg' + null = null), поэтому обязательно используйте функции ISNULL () или COALESCE () для замены нулей пустой строкой, например: ISNULL ('Winnepeg',") + ISNULL (null,").

кроме того, если даже отдаленно возможно, что один из ваших collumns может быть интерпретирован как число, то обязательно используйте функцию CAST (), чтобы избежать возврата ошибок, например: В ролях ('Winnepeg' as varchar (100)).

большинство примеров до сих пор пренебрегают одной или несколькими частями этого. Кроме того, некоторые примеры используют подзапросы или выполняют проверку длины, что вам действительно не следует делать-просто не нужно-хотя ваш оптимизатор может спасти вас в любом случае, если вы это сделаете.

Удачи


некрасиво, но это будет работать для MS SQL:

    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

вот такой вариант:

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