2015-03-09 2 views
1

У меня есть запрос, который возвращает набор данных, который выглядит следующим образом:данных SQL Server Coalesce набор

Region       Name 
------------------------------------------------------------- 
Canada       Jim 
Canada       Michael 
Canada       Andy 
Mexico       Jim 
Mexico       Michael 
Mexico       Kevin 

, но я хочу, чтобы вернуть его, как это вместо:

Region       Name 
------------------------------------------------------------- 
Canada, Mexico     Jim 
Canada, Mexico     Michael 
Canada       Andy 
Mexico       Kevin 

Мой курсор запроса пытается сливаться названия региона, когда имена равны

OPEN RegionCursor 

FETCH NEXT 
FROM RegionCursor 
INTO @regionNext 
    ,@NameNext 

SET @name = @NameNext; 

WHILE @@FETCH_STATUS = 0 
BEGIN 
    IF @NameNext != @name 
    BEGIN 
     INSERT @RegionTable 
     SELECT @region 
      ,@name 

     SELECT @region = @regionNext 
      ,@name = @NameNext 
    END 
    ELSE 
     SET @region = COALESCE(@region + ', ', SPACE(0)) + @regionNext; 

    FETCH NEXT 
    FROM RegionCursor 
    INTO @regionNext 
     ,@NameNext 
END 

INSERT @RegionTable 
SELECT @region 
    ,@name 

CLOSE RegionCursor; 

DEALLOCATE RegionCursor; 

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

+2

Да я не думаю, что COALESCE делает то, что вы думаете, что он делает. –

+0

'COALESCE' является' ISNULL' для множественных провалов. Вы ищете 'CONCAT' – Siyual

+0

' COALESCE (@region + ',', SPACE (0)) 'будет возвращать либо @region, объединенное запятой, либо просто запятую. Он никогда не вернет 'SPACE (0)', поскольку в первом параметре всегда есть что-то ненулевое. Возможно, вы имели в виду 'CASE WHEN @region IS NOT NULL THEN @region + ',' END + @ regionNext' – JNevill

ответ

9

Вам не нужно использовать Cursor XML PATH трюк, чтобы сделать это.

SELECT Name, 
     LEFT(cs.Region, Len(cs.Region) - 1) AS Region       
FROM Yourtable a 
     CROSS APPLY (SELECT Region + ',' 
        FROM Yourtable B 
        WHERE a.name = b.name 
        FOR XML PATH('')) cs (Region) 
GROUP BY Name, 
      LEFT(cs.Region, Len(cs.Region) - 1) 
+0

Upvoted, но это может вызвать странные результаты, когда столбец 'Name' содержит XML зарезервированные символы , –

+1

@BogdanSahlean - Да, это правда. Также хорошо знать об альтернативе. –

1

Вы можете использовать CTE, который может быть немного чище:

;WITH CTE AS 
(SELECT Region, 
     Name, 
     rn = ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Name) 
    FROM Table 
) 
SELECT c1.Region + ',' + c2.Region, 
     c1.Name 
FROM CTE c1 
INNER JOIN CTE c2 ON c2.rn = c1.rn + 1 
+0

, он не выводит результаты по запросу SO – Malcolm

1

Если столбец Name содержит зарезервированные XML-символы (напр. &), то эти "символы" остается кодированный (напр. &) после FOR XML. Чтобы преодолеть эту проблему вы должны использовать value метод:

SELECT ..., oa.RegionsByName 
FROM (SELECT DISTINCT Name FROM dbo.Regions) x 
OUTER APPLY (
    SELECT STUFF(
    (SELECT DISTINCT ',' + y.Name 
    FROM dbo.Regions y 
    WHERE y.Name = x.Name 
    FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS RegionsByName 
) oa 

Вместо NVARCHAR(MAX) пожалуйста, используйте соответствующий тип и макс. длина.

Пример:

SELECT 'C & A' FOR XML PATH('') 
/* 
C & A 
*/ 
SELECT (SELECT 'C & A' FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') 
/* 
C & A 
*/ 
+0

Имена столбцов, содержащие зарезервированные символы xml, не являются частью вопроса OP. Я думаю, что, подняв это, он смущает ответ. – paqogomez

+0

@paqogomez: Это всего лишь безопасный подход. Говоря, что «Имена столбцов, содержащие зарезервированные символы xml, не являются частью вопроса OP», похоже на то, что я знаю, что что-то может пойти не так, но я ничего не делаю. Когда-нибудь я хотел бы смириться с некоторыми путаными комментариями. –

Смежные вопросы