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 列表中获得不同的值顺序。