我有下表:
ID | 数字 | 尺码 |
---|---|---|
7 | 1 | 1.5 |
7 | 2 | 1.5 |
8 | 1 | 1.625 |
8 | 2 | 1.03125 |
8 | 3 | 1.03125 |
8 | 4 | 1.03125 |
8 | 5 | 1.625 |
8 | 6 | 1 |
8 | 7 | 1.625 |
8 | 8 | 1.625 |
8 | 9 | 1.625 |
9 | 1 | 1 |
9 | 2 | 2 |
9 | 3 | 3 |
9 | 4 | 4 |
9 | 5 | 1 |
我想为每个 ID 创建一个包含单个字符串值的列,用于对尺寸进行分组,但前提是这些值基于数字是连续的,并且包括匹配尺寸的数量。
例如,对于ID=8,我想要这样的东西:
1.625 x 1.03125 (x3) x 1.625 x 1 x 1.625 (x3)
请注意,数字可以增加到任何整数值,大小可以是任何正数,最多 7 位小数。
正如我一直在思考的那样,这些是我到目前为止考虑的步骤:
ID | 数字 | 尺码 | 团体 |
---|---|---|---|
7 | 1 | 1.5 | 1 |
7 | 2 | 1.5 | 1 |
8 | 1 | 1.625 | 1 |
8 | 2 | 1.03125 | 2 |
8 | 3 | 1.03125 | 2 |
8 | 4 | 1.03125 | 2 |
8 | 5 | 1.625 | 3 |
8 | 6 | 1 | 4 |
8 | 7 | 1.625 | 5 |
8 | 8 | 1.625 | 5 |
8 | 9 | 1.625 | 5 |
9 | 1 | 1 | 1 |
9 | 2 | 2 | 2 |
9 | 3 | 3 | 3 |
9 | 4 | 4 | 4 |
9 | 5 | 1 | 5 |
ID | 数字 | 尺码 | 团体 | 数量 |
---|---|---|---|---|
7 | 1 | 1.5 | 1 | 2 |
8 | 1 | 1.625 | 1 | 1 |
8 | 2 | 1.03125 | 2 | 3 |
8 | 5 | 1.625 | 3 | 1 |
8 | 6 | 1 | 4 | 1 |
8 | 7 | 1.625 | 5 | 3 |
9 | 1 | 1 | 1 | 1 |
9 | 2 | 2 | 2 | 1 |
9 | 3 | 3 | 3 | 1 |
9 | 4 | 4 | 4 | 1 |
9 | 5 | 1 | 5 | 1 |
最后,可能会结合使用 STRING_AGG() 和 CONCAT() 函数,我会将数据放入以下格式:
ID | 尺码 |
---|---|
7 | 1.5 (x2) |
8 | 1.625 (x1) x 1.03125 (x3) x 1.625 (x1) x 1 (x1) x 1.625 (x3) |
9 | 1 (x1) x 2 (x1) x 3 (x1) x 4 (x1) x 1 (x1) |
而且,我最好省略“(x1)”,这样最终的形式如下所示:
ID | 尺码 |
---|---|
7 | 1.5 (x2) |
8 | 1.625 x 1.03125 (x3) x 1.625 x 1 x 1.625 (x3) |
9 | 1×2×3×4×1 |
有点多。但最后,我希望将这些表中的数据转换为用户更易读的格式,但是 1) 我不确定如何做到这一点,以及 2) 鉴于可能有多种途径来实现这一点,我不确定性能最高的选项是什么。
有什么想法吗?
附言我对任何方法都持开放态度,它当然不必遵循我在此处包含的思路。
*编辑添加新数据集(ID=9)
你有一个gaps and islands problem,一种选择是使用两个
row_number
之间的差异来定义所需的组,使用SQL Server语法尝试以下操作:
with cte1 as -- Step 1: using the difference between two row_numbers approach, create groups for consecutive similar values of Size.
(
select *,
row_number() over (partition by id order by number) -
row_number() over (partition by id, size order by number) grp
from table_name
),
cte2 as -- Step 2: get the counts for each group defined in the previous step
(
select id, min(number) number, size, grp, count(*) cnt
from cte1
group by id, size, grp
)
-- Step 3: use string_agg and concat functions to get the desired format
select id,
string_agg
(-- use a case expression to not include (1x) when count = 1
case when cnt > 1 then concat(size, ' (x', cnt, ')') else cast(size as varchar(20)) end, ' x '
) within group (order by number) Size
from cte2
group by id
order by id