我有这些数据:
{{1}}
我想要一个脚本,在条件上生成三个或四个组:每个组的总和(计数)< 50
我想要这个输出:
{{1}}
答案 0 :(得分:3)
假设必须为每个name
执行此操作,您可以使用递归cte。
with rownums as (select t.*,row_number() over(partition by name order by id) as rnum from t)
,cte(rnum,id,name,cnt,runningsum,grp) as
(select rnum,id,name,cnt,cnt,1 from rownums where rnum=1
union all
select t.rnum,t.id,t.name,t.cnt
,case when c.runningsum+t.cnt > 50 then t.cnt else c.runningsum+t.cnt end
,case when c.runningsum+t.cnt > 50 then t.id else c.grp end
from cte c
join rownums t on t.rnum=c.rnum+1 and t.name=c.name
)
select id,cnt,name,dense_rank() over(partition by name order by grp) as grp
from cte
跟踪运行总和并在超过50时重置它。当总和超过50时,请记住id
。这可用于分配组号。
答案 1 :(得分:1)
对于计数小于50的记录,我们可以通过计算计数的运行总数来简单地生成分组ID,然后将此运行总计除以50.但是,由于某些记录可能已经计数大于或等于50可能会生成错误的ID。为了解决这个问题,我们需要以某种方式强制在下一条记录上生成新的分组ID。如果当前记录计数为50或更大,则可以通过简单地将下一记录的计数调整50来完成。 以下示例演示了如何完成此操作:
CREATE TABLE #Items
(
[Id] INT NOT NULL PRIMARY KEY
,[Name] VARCHAR(50) NOT NULL
,[Count] INT NOT NULL
)
INSERT INTO #Items
VALUES
(1, 'cdd', 50 ),
(2, 'cdd', 15 ),
(3, 'cdd', 0 ),
(4, 'cdd', 25 ),
(5, 'cdd', 11 );
;WITH CTE_ItemCountsAdjusted
AS
(
SELECT [Id]
,[Name]
,[Count]
,LAG([Count], 1, 0) OVER (PARTITION BY [Name] ORDER BY [Id]) AS PrevCount
,(
CASE
WHEN LAG([Count], 1, 0) OVER (PARTITION BY [Name] ORDER BY [Id]) >= 50 THEN [Count] + 50
ELSE [Count]
END
) AdjustedCount
FROM #Items
)
SELECT [Id]
,[Name]
,[Count]
,SUM([AdjustedCount]) OVER (PARTITION BY [Name] ORDER BY [Id] ROWS UNBOUNDED PRECEDING) / 50 AS [Group_number]
FROM CTE_ItemCountsAdjusted
ORDER BY [Id]
此方法消除了递归调用的需要。请注意,如果您需要组ID严格按顺序排列(组号之间没有间隙),那么您可以使用DENSE_RANK()窗口函数来实现此功能,如下例所示:
INSERT INTO #Items
VALUES
(1, 'cdd', 50 ),
(2, 'cdd', 15 ),
(3, 'cdd', 0 ),
(4, 'cdd', 25 ),
(5, 'cdd', 11 ),
(6, 'cdd', 200 ),
(7, 'cdd', 10 );
;WITH CTE_ItemCountsAdjusted
AS
(
SELECT [Id]
,[Name]
,[Count]
,LAG([Count], 1, 0) OVER (PARTITION BY [Name] ORDER BY [Id]) AS PrevCount
,(
CASE
WHEN LAG([Count], 1, 0) OVER (PARTITION BY [Name] ORDER BY [Id]) >= 50 THEN [Count] + 50
ELSE [Count]
END
) AdjustedCount
FROM #Items
),CTE_ItemCountsWithGroupID
AS
(
SELECT [Id]
,[Name]
,[Count]
,SUM([AdjustedCount]) OVER (PARTITION BY [Name] ORDER BY [Id] ROWS UNBOUNDED PRECEDING) / 50 AS [Group_number]
FROM CTE_ItemCountsAdjusted
)
SELECT [Id]
,[Name]
,[Count]
,[Group_number]