t-sql使用dense_rank将记录与where条件分组

时间:2014-04-09 04:27:30

标签: sql-server sql-server-2008 tsql

实际数据:

division    ID          order       date     
ABC123      ZZZ123      ORDERT1     1/17/2013       
ABC123      ZZZ123      1111112     1/25/2013       
ABC123      ZZZ123      ORDERT2     2/22/2013       
ABC123      ZZZ123      1234567     2/26/2013       
ABC123      YYY222      ORDERT2     3/20/2013       
XYZ456      ZZZ123      5555555     2/09/2012       
XYZ456      ZZZ123      ORDERT2     4/13/2012       
XYZ456      ZZZ123      5555777     6/23/2012       
XYZ456      ZZZ123      ORDERT2     10/5/2012       
XYZ456      ZZZ123      8888899     11/18/2012 

对于给定数据,当订单类似于'ORDER%'时,应启动新的ORDER_group。每个应按division, ID分组,并按date排序。

我原以为我可以按DENSE_RANK进行division, ID分区,但是当订单类似于group

时,我需要“更改”'ORDER%'

预期结果:

division    ID          order       date        ORDER_group
ABC123      ZZZ123      ORDERT1     1/17/2013   1    
ABC123      ZZZ123      1111112     1/25/2013   1   
ABC123      ZZZ123      ORDERT2     2/22/2013   2    
ABC123      ZZZ123      1234567     2/26/2013   2    
ABC123      YYY222      ORDERT2     3/20/2013   1    
XYZ456      ZZZ123      5555555     2/09/2012   1    
XYZ456      ZZZ123      ORDERT2     4/13/2012   2    
XYZ456      ZZZ123      5555777     6/23/2012   2    
XYZ456      ZZZ123      ORDERT2     10/5/2012   3    
XYZ456      ZZZ123      8888899     11/18/2012  3

请注意,当divisionID发生变化时,ORDER_group也会发生变化。应该假设所有记录的order_group都是1.一旦给定记录遇到像'ORDER%'这样的值的订单,它应该增加给定分区/ ID的order_group;所有按日期排序,以保持秩序。

希望我已经完全说明了我正在尝试做的事情。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

我认为使用DENSE_RANK是不可能的。这是因为无法知道1111112属于ORDERT1因此sql将如何进入GROUP BY

我能够使用循环来做到这一点。另外,我假设表中当前存在的数据已按divisionid排序,表格中显示的方式。

另外,不确定它的性能如何。

DECLARE @MainTable TABLE
(
    division VARCHAR(10),
    Id VARCHAR(10),
    [order] VARCHAR(10),
    [date] DATETIME
)

INSERT INTO @MainTable VALUES('ABC123','ZZZ123','ORDERT1','1/17/2013')
INSERT INTO @MainTable VALUES('ABC123','ZZZ123','1111112','1/25/2013')
INSERT INTO @MainTable VALUES('ABC123','ZZZ123','ORDERT2','2/22/2013')
INSERT INTO @MainTable VALUES('ABC123','ZZZ123','1234567','1/22/2013')
INSERT INTO @MainTable VALUES('ABC123','YYY222','ORDERT2','3/20/2013')
INSERT INTO @MainTable VALUES('XYZ456','ZZZ123','5555555','2/09/2012')
INSERT INTO @MainTable VALUES('XYZ456','ZZZ123','ORDERT2','4/13/2012')
INSERT INTO @MainTable VALUES('XYZ456','ZZZ123','5555777','6/23/2012')
INSERT INTO @MainTable VALUES('XYZ456','ZZZ123','ORDERT2','10/5/2012')
INSERT INTO @MainTable VALUES('XYZ456','ZZZ123','8888899','11/18/2012')

DECLARE @RequiredTable TABLE
(
    RowId INT IDENTITY(1,1),
    division VARCHAR(10),
    Id VARCHAR(10),
    [order] VARCHAR(10),
    [date] DATETIME,
    ORDER_GROUP INT
)
DECLARE @StartCount INT, @LastCount INT
DECLARE @division VARCHAR(10),
    @Id VARCHAR(10),
    @order VARCHAR(10),
    @date DATETIME,
    @ORDER_GROUP INT


SELECT @StartCount = 1, @ORDER_GROUP = 1
SELECT @LastCount = COUNT(0) FROM @MainTable

WHILE(@StartCount <= @LastCount)
BEGIN
    IF(@StartCount = 1)
    BEGIN
        INSERT INTO @RequiredTable
        (
            division,
            Id ,
            [order] ,
            [date] ,
            ORDER_GROUP
        )
        SELECT division,
        Id,
        [order],
        [date], 
        1
        FROM
        (SELECT ROW_NUMBER() OVER (ORDER BY division) AS ROWNUM, * 
        FROM @MainTable) tbl
        WHERE ROWNUM = @StartCount
    END
    ELSE
    BEGIN
        SELECT @division = division,
        @Id = Id,
        @order  = [order],
        @date = [date]
        FROM
        (SELECT ROW_NUMBER() OVER (ORDER BY division) AS ROWNUM, * 
        FROM @MainTable) tbl
        WHERE ROWNUM = @StartCount

        IF EXISTS(SELECT 0 FROM @RequiredTable WHERE RowId = @StartCount - 1 AND division = @division AND Id = @Id)
        BEGIN
            IF(SUBSTRING(@order,1,5) = 'ORDER')
            BEGIN
                SET @ORDER_GROUP = @ORDER_GROUP + 1
            END
        END
        ELSE
        BEGIN
            SET @ORDER_GROUP = 1
        END

        INSERT INTO @RequiredTable
        (
            division,
            Id ,
            [order] ,
            [date] ,
            ORDER_GROUP
        )
        VALUES (@division,
        @Id,
        @order,
        @date, 
        @ORDER_GROUP)
    END

    SET @StartCount = @StartCount + 1
END

SELECT * FROM @RequiredTable

希望这有帮助。