Group_Concat в парах nth

У меня есть запрос, который я обычно group_concat, Мне нужно знать, если dbo.group_concat имеет возможность объединить результат запроса в пары по 3 (в качестве примера).

Например:

select size, pattern, dbo.group_concat(mass) mass 
from labels 
group by size, pattern

Результат

Size Pattern Mass 
-----------------------------------------------------------
234  ZYL     22.43,55.32,33.24,22.53,56.32,40.32,50.21,32.21
234  ZA      50.00,56.23,21.23,50.21

Я хотел бы получить этот результат

Size Pattern  Mass
--------------------------------
234  ZYL      22.43,55.32,33.24
234  ZYL      22.53,56.32,40.32
234  ZYL      50.21,32.21
234  ZA       50.00,56.23,21.23
234  ZA       50.21 

1 ответ

Это можно сделать легко, если у нас есть group ID колонка. Этот столбец будет группировать строки по три, сортируя данные по [mass] значение. Так как у нас нет такой колонки, нам нужно ее рассчитать. Шаги как следующие:

  1. мы используем ROW_NUMBER функция сортировки строк и знать, какие три строки следствия образуют группу
  2. затем мы используем рекурсивное общее табличное выражение (ничего сложного) - просто получаем первую строку каждого size, pattern сущность, а затем присоединиться к следующему ряду... затем присоединиться к следующему, пока мы не получим их все

Это полный рабочий пример выше:

DECLARE @DataSource TABLE
(
    [size] VARCHAR(12)
   ,[pattern] VARCHAR(12)
   ,[mass] DECIMAL(9,2)
);


INSERT INTO @DataSource ([size], [pattern], [mass])
VALUES (234, 'ZYL', 22.43)
      ,(234, 'ZYL', 55.32)
      ,(234, 'ZYL', 33.24)
      ,(234, 'ZYL', 22.53)
      ,(234, 'ZYL', 56.32)
      ,(234, 'ZYL', 40.32)
      ,(234, 'ZYL', 50.21)
      ,(234, 'ZYL', 32.21)
      --
      ,(234, 'ZA', 50.00)
      ,(234, 'ZA', 56.23)
      ,(234, 'ZA', 21.23)
      ,(234, 'ZA', 50.21);

WITH DataSource AS 
(
    SELECT *
          ,ROW_NUMBER() OVER (PARTITION BY [size], [pattern] ORDER BY [mass]) AS [RowID]
    FROM @DataSource
),
RecursiveDataSource AS
(
    SELECT [size], [pattern], [mass], [RowID]
          ,1 AS [Group]
    FROM DataSource
    WHERE [RowID] = 1
    UNION ALL
    SELECT A.*
          ,R.[Group] + CASE WHEN (A.[rowID] - 1) % 3 = 0 THEN 1 ELSE 0 END
    FROM DataSource A
    INNER JOIN RecursiveDataSource R
        ON A.[size] = R.[size]
        AND A.[pattern] = R.[pattern]
        AND A.[RowID] - 1 = R.[rowID]
)
SELECT *
FROM RecursiveDataSource
ORDER BY [pattern], [RowID];

Теперь в финале SELECT нам просто нужно добавить ваш исходный код, но сгруппировать по [group] колонка также:

SELECT [size], [pattern], [dbo].[group_concat] ([mass])
FROM RecursiveDataSource
GROUP BY [size], [pattern], [Group];

В моей системе вышесказанное дает следующее:

Некоторые соображения:

  • Я упорядочиваю значения по mass ценность (а в вашем примере это не так) - это полностью ваше дело; Вы можете изменить порядок на все, что вам нужно, даже используя SELECT 1 в ORDER BY пункт о ROW_NUMBER функция для получения случайного порядка;
  • использование рекурсивного CTE для большой таблицы может привести к снижению производительности; убедитесь, что сначала проверили код с вашими реальными данными;
  • concatenate Функция SQL CLR в моих системах позволяет устанавливать порядок; в моем случае я соединил строки, используя RowID значение; если ваша функция не позволяет указывать такой порядок, вы полагаетесь на код.net, стоящий за ней, поэтому вы можете получить другой порядок значений в окончательном списке CSV.
Другие вопросы по тегам