Як використовувати COALESCE з кількома рядками та без попередніх коми?


27

Я намагаюся досягти наступного:

California | Los Angeles, San Francisco, Sacramento
Florida    | Jacksonville, Miami

На жаль, я отримую ", Лос-Анджелес, Сан-Франциско, Сакраменто, Джексонвілл, Маямі"

Я можу досягти бажаних результатів за допомогою функції STUFF, але мені було цікаво, чи існує більш чистий спосіб зробити це за допомогою COALESCE?

STATE       | CITY
California  | San Francisco
California  | Los Angeles
California  | Sacramento
Florida     | Miami
Florida     | Jacksonville 


DECLARE @col NVARCHAR(MAX);
SELECT @col= COALESCE(@col, '') + ',' + city
FROM tbl where city = 'California';
SELECT @col;

Спасибі

Відповіді:


45

Це може бути більш чистим підходом, який ви дотримуєтесь. По суті, перевірте, чи змінена ініціалізована ще. Якщо цього немає, встановіть його в порожній рядок і додайте перше місто (немає першої коми). Якщо є, то додайте кому, а потім додайте місто.

DECLARE @col nvarchar(MAX);
SELECT @col = COALESCE(@col + ',', '') + city
  FROM dbo.tbl WHERE state = 'California';

Звичайно, це працює лише для заповнення змінної на стан. Якщо ви тягнете список для кожної держави по черзі, є краще рішення за один кадр:

SELECT [state], cities = STUFF((
    SELECT N', ' + city FROM dbo.tbl
    WHERE [state] = x.[state]
    FOR XML PATH(''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 2, N'')
FROM dbo.tbl AS x
GROUP BY [state]
ORDER BY [state];

Результати:

state       cities
----------  --------------------------------------
California  San Francisco, Los Angeles, Sacramento  
Florida     Miami, Jacksonville

Щоб замовити назву міста в кожному штаті:

SELECT [state], cities = STUFF((
    SELECT N', ' + city FROM dbo.tbl
    WHERE [state] = x.[state]
    ORDER BY city
    FOR XML PATH(''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 2, N'')
FROM dbo.tbl AS x
GROUP BY [state]
ORDER BY [state];

У базах даних Azure SQL або SQL Server 2017+ ви можете використовувати нову STRING_AGG()функцію :

SELECT [state], cities = STRING_AGG(city, N', ')
  FROM dbo.tbl
  GROUP BY [state]
  ORDER BY [state];

І впорядковано за назвою міста:

SELECT [state], cities = STRING_AGG(city, N', ') 
                         WITHIN GROUP (ORDER BY city)
  FROM dbo.tbl
  GROUP BY [state]
  ORDER BY [state];

Спасибі Аарон Моє поточне рішення майже ідентичне вашому, за винятком того, що я використовую DISTINCT замість GROUP BY.
користувач2732180

2
@ user2732180 Ви повинні використовувати GROUP BY, оскільки більш ймовірно виконувати конкатенацію один раз у кожному стані. Наприклад, з DISTINCT він застосовуватиме однакову конкатенацію для кожного екземпляру Каліфорнії, і лише тоді відкидає всю роботу, яку він зробив, створюючи ці дублікати.
Аарон Бертран

6

Просто для додання відповіді Аарона вище ...

Майте на увазі, що порушення ORDER BYможе порушитися, включивши лише останній елемент у ваш запит. У моєму випадку я не групувався, тому не впевнений, чи це має значення. Я використовую SQL 2014. У моєму випадку у мене є щось на зразок value1, value2, value3 ... але моїм результатом у змінній було лише value3.


Аарон прокоментував:

Про це повідомлялося щонайменше чотири рази на Connect:

  1. У змінній конкатенації та впорядкуванні за результатами фільтрів (наприклад, де умова)
  2. (n) варчарська будівля з ResultSet не вдається, коли додано ЗАМОВЛЕННЯ
  3. Призначення локальної змінної від упорядкованого SELECT за допомогою CROSS APPLYs та функції з табличним значенням повертає лише останнє значення
  4. При об'єднанні значень varchar (max) / nvarchar (max) з змінної таблиці, неправильні результати можуть бути повернуті, якщо фільтрувати та замовляти стовпчик не первинного ключа

Приклад відповіді від Microsoft:

Поведінка, яку ви бачите, - це дизайн. Використання операцій присвоєння (конкатенація в цьому прикладі) у запитах із пунктом ORDER BY має невизначене поведінку.

У відповіді також посилається KB 287515:

PRB: План виконання та результати запитів сукупного об'єднання залежать від місця виразу

Рішення полягає у використанні FOR XML PATH(другий підхід у відповіді Аарона), якщо порядок конкатенації важливий і, звичайно, якщо ви хочете обов'язково включити всі значення. Також дивіться:

nvarchar конкатенація / індекс / nvarchar (макс.) незрозуміла поведінка під час переповнення стека

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.