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]
значение. Так как у нас нет такой колонки, нам нужно ее рассчитать. Шаги как следующие:
- мы используем
ROW_NUMBER
функция сортировки строк и знать, какие три строки следствия образуют группу - затем мы используем рекурсивное общее табличное выражение (ничего сложного) - просто получаем первую строку каждого
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.