Объединить значения sql в переменную - PullRequest
7 голосов
/ 25 января 2011

В SQL Server 2008 я пытаюсь получить разделенный запятыми список всех выбранных значений в переменную.

SELECT field
FROM table

возвращает:

+-------+
| field |
+-------+
| foo   |
+-------+
| bar   |
+-------+

Я бы хотелчтобы получить: "foo, bar"

Я пытался:

DECLARE @foo NVARCHAR(MAX)
SET @foo = ''

SELECT @foo = @foo + field + ','
FROM TABLE

PRINT @foo

, который ничего не возвращает.Что я делаю не так?

Ответы [ 4 ]

9 голосов
/ 25 января 2011

Вам нужно будет изменить NULL

SELECT @foo = @foo + ISNULL(field + ',', '')
FROM TABLE

или удалите их

SELECT @foo = @foo + field + ','
FROM TABLE
WHERE field IS NOT NULL
3 голосов
/ 25 января 2011

Это происходит, если в таблице есть даже одно поле, равное NULL.В SQL Server NULL + <any> = NULL.Или опустите их

SELECT @foo = @foo + field + ','
FROM TABLE
WHERE field is not null

Или обойдите их

SELECT @foo = @foo + isnull(field + ',', '')
FROM TABLE

Вы можете написать все это без ведущего оператора SET, который более распространен.Этот запрос ниже возвращает "foo, bar" без запятой

DECLARE @foo NVARCHAR(MAX)
SELECT @foo = isnull(@foo + ',', '') + field
FROM TABLE
WHERE field is not null

PRINT @foo
1 голос
/ 05 июля 2019

В соответствии с комментарием Лукаша Шозды, сделанным к одному из ответов, вы не должны использовать указанный метод для агрегирования строковых значений в SQL Server, так как эта функция не поддерживается. Хотя это имеет тенденцию работать, когда не используется ни одно из положений заказа (и даже если исключение из этой тенденции никогда не было задокументировано), Microsoft не гарантирует, что это будет работать, и всегда есть вероятность, что оно может перестать работать в будущем. SQL является декларативным языком; Вы не можете предполагать, что поведение, которое явно не определено как правильное поведение для интерпретации данного оператора, продолжит работать.

Вместо этого см. Примеры ниже или на этой странице приведен обзор допустимых способов достижения того же результата и их соответствующей производительности: Оптимальный способ объединения / агрегирования строк

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

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

--Null values treated as empty strings
SET @Foo =
    STUFF /*Stuff is used to remove the seperator from the start of the string*/
        (   (SELECT N','/*separator*/ + ISNULL(RTRIM(t.Field), '' /*Use an emptry string in the place of NULL values*/) /*Thing to List*/
            FROM TABLE t
            ORDER BY t.SomeUniqueColumn ASC /*Make the query deterministic*/
            FOR XML PATH, TYPE).value(N'.[1]',N'varchar(max)')
        ,1
        ,1 /*Length of separator*/
        ,N'');

--Null values excluded from result
SET @Foo =
    STUFF /*Stuff is used to remove the seperator from the start of the string*/
        (   (SELECT N','/*separator*/ + RTRIM(t.Field) /*Thing to List*/
            FROM TABLE t
            WHERE t.Field IS NOT NULL
            ORDER BY t.SomeUniqueColumn ASC /*Make the query deterministic*/
            FOR XML PATH, TYPE).value(N'.[1]',N'varchar(max)')
        ,1
        ,1 /*Length of separator*/
        ,N'');
1 голос
/ 16 декабря 2011

Не забудьте использовать LTRIM и RTRIM вокруг @foo (когда тип данных char / varchar) в конкатенации, иначе это не даст ожидаемых результатов в SQL 2008 R2.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...