当累积列小于或等于目标时设置组数

Posted

技术标签:

【中文标题】当累积列小于或等于目标时设置组数【英文标题】:Set a Group number when cumulative column less than or equal to target 【发布时间】:2020-07-07 19:08:58 【问题描述】:

我有一列包含一个网站有多少子链接。

我的表架构是 id、sub_link、link

id  sub_link link group
1   5   link1.com   1
2   2   link2.com   2
3   4   link3.com   3
4   1   link4.com   3
4   1   link4.com   3
5   2   link5.com   4
6   4   link6.com   5
7   3   link7.com   6
7   3   link7.com   6

当 sub_link 的总数等于或小于 5 时,我想添加一个带有组号的列,同时避免重复。

我不知道从哪里开始,因为我只能编写选择语句并进行一些连接。 也许有一种使用窗口函数或 CTE 的方法,我更喜欢进一步体验。

这是一个小提琴链接

https://www.db-fiddle.com/f/6rmtcazWaWvLULZ5QgpmSb/1

感谢您的帮助。

【问题讨论】:

为什么值是 1-6 而不是 1-7? 这并不完美,但它接近? sum(sub_links) over (order by id) / 5 我们需要将您的尝试和您的 DDL/DML 作为问题的一部分 - 提琴很有帮助,但问题需要单独存在。 我认为这个更接近:(sum(sub_links) over (order by id) - 1) / 5 + 1 尽管对于具有相同id 的行集,这会有问题。 感谢您的 cmets,我在第一个答案的评论中更详细地解释了逻辑。我没有 DDL/DML,只是将这张表导出给我并完成了这项任务。 【参考方案1】:

根据您在下面的评论,除了在单独的临时表中跟踪滚动的 Sub_link 总和之外,我不确定如何执行此操作。下面是一个例子。如果您只需要跟踪当前记录和以前记录的子链接,则可能是使用 LAG function 的单个查询来完成的方法。

USE [master]
GO
CREATE DATABASE [Test]
GO

USE [Test]
GO

CREATE TABLE [Test] (
    ID INT
  , Sub_Links TINYINT
  , Link VARCHAR(100)
);

INSERT INTO [Test]
VALUES (1, 5, 'link1.com')
    , (2, 2, 'link2.com') 
    , (3, 4, 'link3.com')
    , (4, 1, 'link4.com')
    , (4, 1, 'link4.com')
    , (5, 2, 'link5.com')
    , (6, 4, 'link6.com')
    , (7, 3, 'link7.com')
    , (7, 3, 'link7.com');

SET NOCOUNT ON
GO
CREATE TABLE #Staging
(
      ID INT
    , Link VARCHAR(100)
    , Sub_Links INT
    , GroupNum INT
    , SublinkRollingSum TINYINT
)
GO

CREATE CLUSTERED INDEX [StagingOrder] ON #Staging(ID, Link) --Since need to guarantee order, doing this upfront should be more efficient
GO

INSERT INTO #Staging(ID, Link, Sub_Links)
SELECT DISTINCT --Don't include duplicate records
      ID
    , Link
    , Sub_Links
FROM Test
ORDER BY ID, Link
GO
--CREATE INDEX [GroupIndex] ON #Staging(GroupNum, SublinkRollingSum)--Intended to improve performance of below while loop
--GO

WITH FirstRecord AS
(
    SELECT TOP(1) *
    FROM #Staging
    ORDER BY ID, Link
)
UPDATE FirstRecord
SET GroupNum = 1, SublinkRollingSum = Sub_Links --This is the starting point

DECLARE 
      @CurrentID INT
    , @CurrentLink VARCHAR(100)
    , @CurrentGroup INT
    , @SublinkRollingSum TINYINT

SELECT TOP(1) 
      @CurrentID = ID
    , @CurrentLink = Link
    , @CurrentGroup = GroupNum
    , @SublinkRollingSum = SublinkRollingSum
FROM #Staging
ORDER BY ID, Link

WHILE (@@ROWCOUNT > 0)
BEGIN
    UPDATE #Staging
    SET   SublinkRollingSum = @SublinkRollingSum
        , GroupNum = @CurrentGroup
    WHERE ID = @CurrentID
        AND Link = @CurrentLink

    SELECT TOP(1)
          @CurrentID = ID
        , @CurrentLink = Link
        , @CurrentGroup = 
            CASE 
                WHEN (@SublinkRollingSum + Sub_Links <= 5) 
                    THEN @CurrentGroup
                ELSE @CurrentGroup + 1
            END
        , @SublinkRollingSum = 
            CASE 
                WHEN (@SublinkRollingSum + Sub_Links <= 5) 
                    THEN @SublinkRollingSum + Sub_Links
                ELSE Sub_Links
            END
    FROM #Staging
    WHERE ID > @CurrentID 
        OR (ID = @CurrentID AND Link <> @CurrentLink)
    ORDER BY ID, Link
END

SELECT 
      t.ID
    , t.Sub_Links
    , t.Link
    , s.GroupNum
FROM #Staging S
    JOIN Test t ON s.ID = t.ID
        AND s.Link = t.Link
ORDER BY t.ID, t.Link

DROP TABLE #Staging

--DROP DATABASE [Test]

【讨论】:

感谢您的询问。正确我需要添加一列,其中包含一个组号,其中每个组最多包含 5 个。在我的示例中,第一个障碍是重复,然后我将手动编写逻辑 id = 1, sub = 5 然后 group = 1 id =2, sub = 2 + previous 5 = more than 5 then new group = 2(因为 1 是完整)id = 3,sub = 4 + prev 2 = 6 超过 5 然后新组 = 3(第 2 组只有 id 2,因为 4 超过 5)id = 4(重复然后避免第一行或第二行) , sub = 1,也是第 3 组,因为 prev 4 + 1 = 5 next 将是第 4 组,依此类推。 我解释清楚了,这就是群栏的逻辑 @hatahetahmad - 获取组不仅仅是之前考虑的 sub_link 值?例如。 id = 1,子 = 1,组 = 1; id = 2,sub = 2,group = 1(因为 2 + 1 5???另外,sub_link 的值是 0 吗? 谢谢亲爱的,这是正确的组=2,因为1 + 3 + 2 > 5,也没有0的情况,也没有子链接超过5的情况。子链接总是 [1:5]

以上是关于当累积列小于或等于目标时设置组数的主要内容,如果未能解决你的问题,请参考以下文章

我可以检查散列密码是不是等于 laravel 中的特定值?

根据另一列熊猫设置列等于值

python如何设置变量等于0或1

使用事件值条件等于0时,目标转换未注册

excel条件格式 不等于怎么操作

excel a列输入数值时 b列显示红色